目標讀者:不需要自己訓練模型,但需要深刻理解 LLM 能做什么、不能做什么、為什么會出錯的工程師和產(chǎn)品人。
一、LLM 是什么
1.1 一句話定義
LLM(Large Language Model,大語言模型)本質(zhì)上是一個概率預測機器:
給定前面所有的文字,預測下一個詞(Token)最可能是什么。
就這么簡單。但正是這個看似簡單的任務(wù),在超大規(guī)模數(shù)據(jù)和參數(shù)下,涌現(xiàn)出了推理、寫作、編程、翻譯等復雜能力。
1.2 Token 是什么
LLM 處理的基本單位不是"字",而是 Token。
英文:
"Hello, world!" → ["Hello", ",", " world", "!"] → 4 個 Token
中文:
"你好世界" → ["你好", "世界"] → 2 個 Token
(中文通常 1~2 個漢字對應(yīng) 1 個 Token)
代碼:
"print('hello')" → ["print", "('", "hello", "')"] → 4 個 Token
關(guān)鍵數(shù)字:
- GPT-4 的上下文窗口:128K Token ≈ 約 10 萬個漢字
- Claude 3.5:200K Token ≈ 約 15 萬個漢字
- 1000 Token ≈ 750 個英文單詞 ≈ 500 個漢字
二、Transformer:LLM 的核心架構(gòu)
2.1 架構(gòu)全景
輸入文本(字符串)
↓
[Tokenizer] 文本 → Token ID 序列
"今天天氣" → [1234, 5678, 9012]
↓
[Embedding 層] Token ID → 向量
每個 ID 映射為一個高維浮點數(shù)向量
[1234] → [0.12, -0.34, 0.87, ...]
↓
[N × Transformer Block]
├── [Self-Attention] 每個 Token 關(guān)注其他所有 Token,更新向量表示
└── [FFN] 前饋網(wǎng)絡(luò),進一步提取特征
↓
[輸出層(Linear + Softmax)]
最后一個位置的向量 → 詞表上每個 Token ID 的概率分布
{1234: 0.01, 5678: 0.60, 9012: 0.02, ...}
↓
[采樣] 根據(jù)概率分布選出下一個 Token ID
→ 選出 ID: 5678
↓
[Detokenizer] Token ID → 文本
5678 → "很"
↓
輸出文本(字符串)"很"
↓
[將新 Token 追加到輸入,循環(huán)執(zhí)行,直到生成結(jié)束符 <EOS>]
2.2 Self-Attention:最關(guān)鍵的機制
用一個完全不涉及數(shù)學的例子來理解。
大白話例子:開會投票決定誰說了算
想象你在處理這句話:
"小明把球給了小紅,因為他很累了。"
現(xiàn)在的問題是:"他" 指的是誰?小明還是小紅?
第一步:每個詞都有一張"名片"和一張"問卷"
句子里每個詞,系統(tǒng)給它準備兩樣東西:
- 名片(Key):寫著"我是誰,我有什么特征"
- 問卷(Query):寫著"我想找什么樣的詞"
小明 的名片:男性、人名、主語、做了動作
小紅 的名片:女性、人名、賓語、接受了球
他 的問卷:我想找 → 男性、人名、主語
這張"名片"是人工打的嗎?
不是。沒有任何人手動標注"小明是男性、人名、主語"。
名片(Key)、問卷(Query)、內(nèi)容(Value)全部是訓練出來的:
每個詞先變成一串數(shù)字(Embedding 向量),然后乘以三個矩陣(W_Q、W_K、W_V),
分別得到 Q、K、V。這三個矩陣是模型在訓練過程中自動學習出來的參數(shù)。模型在訓練時看了海量文本,發(fā)現(xiàn)"他/她/它"后面接的內(nèi)容,往往和前面某個名詞有關(guān)——
不斷調(diào)整這三個矩陣,讓"他的問卷"和"小明的名片"自然而然地匹配度更高。所以"男性、人名、主語"只是我們用人話描述的直覺,
真實的名片是一串幾百維的浮點數(shù),沒有人能直接讀懂,
但它的效果等價于"描述了這個詞的語言特征"。
第二步:拿著問卷去匹配所有名片,打分
"他"拿著自己的問卷,挨個去和其他詞的名片對照:
"他"的問卷 vs 小明的名片 → 男性? 人名? 主語? → 匹配度:90分
"他"的問卷 vs 小紅的名片 → 男性? 人名? 主語? → 匹配度:20分
"他"的問卷 vs 球的名片 → 男性? 人名? 主語? → 匹配度:2分
"他"的問卷 vs 因為的名片 → ... → 匹配度:1分
第三步:按分數(shù)決定"借多少信息"
分數(shù)高的詞,"他"就多借一點它的信息;分數(shù)低的詞,少借或者不借:
"他"最終的理解 =
90% × 小明的含義
+ 20% × 小紅的含義(歸一化后)
+ 2% × 球的含義
+ ...
歸一化之后大概是:
72% × 小明 + 16% × 小紅 + 2% × 球 + ...
結(jié)果:"他"這個詞現(xiàn)在已經(jīng)帶上了大量"小明"的信息。
后續(xù)模型繼續(xù)生成文字時,就"知道"了——他 = 小明。
第四步:每個詞都同時做這件事
不只是"他"在做,句子里每一個詞都同時在做同樣的事:
小明 → 看了所有詞,更新自己(知道自己是主語,給了球)
球 → 看了所有詞,更新自己(知道自己被傳遞了)
小紅 → 看了所有詞,更新自己(知道自己是接球的人)
他 → 看了所有詞,更新自己(知道自己指的是小明)
累了 → 看了所有詞,更新自己(知道是小明累了)
所有詞同時互相"看"一遍,每個詞都吸收了整個句子的上下文信息。
這就是"Self"(自身序列內(nèi)部互相關(guān)注)的含義。
第五步:不止看一個角度(Multi-Head)
上面的例子只從"指代關(guān)系"這一個角度看。現(xiàn)實中模型同時開 32~128 個"視角",每個視角關(guān)注不同的語言關(guān)系:
視角1(指代關(guān)系):他 → 小明
視角2(動作關(guān)系):累了 → 小明(誰累了?)
視角3(位置關(guān)系):因為 → 連接前后兩個事件
視角4(語氣關(guān)系):...
...
視角N:...
最終把所有視角的結(jié)果拼在一起 → 全面理解這個句子
用一句話總結(jié) Self-Attention
句子里的每個詞,都去"問"其他所有詞:"你跟我有多相關(guān)?",
然后按相關(guān)程度,從每個詞那里借一點信息,
把這些信息混合在一起,更新自己的理解。
所有詞同時做這件事,一輪結(jié)束后,每個詞都"看懂"了整個句子的上下文。
Q、K、V 對應(yīng)關(guān)系
現(xiàn)在再看這三個術(shù)語,就很好理解了:
| 術(shù)語 | 大白話 | 例子中對應(yīng) |
|---|---|---|
| Q(Query,查詢) | 我的問卷,我在找什么 | "他"想找:男性、人名、主語 |
| K(Key,鍵) | 我的名片,我有什么特征 | 小明的名片:男性、人名、主語 |
| V(Value,值) | 我的實際內(nèi)容 | 小明這個詞完整的語義信息 |
公式 Attention(Q, K, V) = softmax(QK^T / √d) × V 做的就是:
用 Q 和 K 算匹配分數(shù) → softmax 變成百分比 → 按百分比加權(quán)取 V。
Causal Mask:生成時不能"偷看未來"
還有一個重要限制:模型生成文字時,是一個詞一個詞往后寫的,后面的詞還沒生成,所以不能用。
正在生成第5個詞時:
能看到:詞1 詞2 詞3 詞4 [正在生成詞5]
不能看:詞6 詞7 詞8 ...(還不存在)
就像考試時:
你只能參考已經(jīng)寫下的答案,不能看還沒寫的部分
系統(tǒng)通過把"未來位置"的匹配分數(shù)強制設(shè)為負無窮,讓它們經(jīng)過 softmax 后權(quán)重變成 0,等效于視而不見。
訓練期原理:W_Q/W_K/W_V 是怎么一步步生成的
用一個極小的例子,數(shù)字都是手算得出的,方便理解完整過程。
場景設(shè)定
詞表只有 3 個詞:貓、喜歡、魚
訓練樣本:給模型看 "貓 喜歡" → 讓它預測下一個詞是 "魚"
向量維度設(shè)為 2(現(xiàn)實中是幾千維,這里為了手算用 2)。
第一步:把詞變成向量(Embedding)
先給每個詞一個初始向量(隨機數(shù),訓練會調(diào)整):
貓 → [1.0, 0.5]
喜歡 → [0.3, 0.8]
魚 → [0.9, 0.1]
輸入 "貓 喜歡" 時,得到兩個向量:
x_貓 = [1.0, 0.5]
x_喜歡 = [0.3, 0.8]
第二步:隨機初始化 W_Q、W_K、W_V
訓練開始時,這三個矩陣都是隨機數(shù):
W_Q = [[0.1, 0.2], W_K = [[0.4, 0.1], W_V = [[0.3, 0.5],
[0.3, 0.4]] [0.2, 0.3]] [0.1, 0.2]]
(現(xiàn)實中這些矩陣是幾千×幾千維,這里用 2×2 示意)
第三步:計算 Q、K、V(前向傳播)
用每個詞的 Embedding 乘以三個矩陣,得到 Q/K/V:
Q_貓 = x_貓 × W_Q = [1.0, 0.5] × W_Q = [0.25, 0.40]
K_貓 = x_貓 × W_K = [1.0, 0.5] × W_K = [0.50, 0.25]
V_貓 = x_貓 × W_V = [1.0, 0.5] × W_V = [0.35, 0.60]
Q_喜歡 = x_喜歡 × W_Q = [0.3, 0.8] × W_Q = [0.27, 0.38]
K_喜歡 = x_喜歡 × W_K = [0.3, 0.8] × W_K = [0.28, 0.27]
V_喜歡 = x_喜歡 × W_V = [0.3, 0.8] × W_V = [0.17, 0.31]
第四步:計算 Attention 權(quán)重("喜歡"該關(guān)注誰?)
用 Q_喜歡 分別和 K_貓、K_喜歡 做點積,算匹配分數(shù):
score(喜歡→貓) = Q_喜歡 · K_貓
= 0.27×0.50 + 0.38×0.25 = 0.135 + 0.095 = 0.230
score(喜歡→喜歡) = Q_喜歡 · K_喜歡
= 0.27×0.28 + 0.38×0.27 = 0.076 + 0.103 = 0.179
經(jīng)過 Softmax 變成權(quán)重(兩個加起來=1):
weight(喜歡→貓) = 0.513
weight(喜歡→喜歡) = 0.487
"喜歡" 對 "貓" 的關(guān)注度略高(51% vs 49%)。
第五步:加權(quán)求和 V,得到"喜歡"的新向量
output_喜歡 = 0.513 × V_貓 + 0.487 × V_喜歡
= 0.513 × [0.35, 0.60] + 0.487 × [0.17, 0.31]
= [0.180, 0.308] + [0.083, 0.151]
= [0.263, 0.459]
這個 [0.263, 0.459] 就是"喜歡"經(jīng)過 Attention 后的新向量,
它已經(jīng)融合了"貓"的信息。
第六步:用新向量預測下一個詞
把 output_喜歡 經(jīng)過最后一層,得到詞表上每個詞的概率:
預測結(jié)果:
貓 → 15%
喜歡 → 10%
魚 → 75% ← 模型預測"魚"的概率最高
第七步:和正確答案對比,算誤差(Loss)
正確答案是 "魚",對應(yīng)的目標是:
目標:貓=0%, 喜歡=0%, 魚=100%
預測:貓=15%, 喜歡=10%, 魚=75%
Loss(誤差)= 預測和目標的差距
= 用交叉熵公式算出一個數(shù),比如 0.288
Loss 越大,說明預測越不準,需要調(diào)整。
第八步:反向傳播,調(diào)整 W_Q、W_K、W_V
這是訓練的核心。根據(jù) Loss,計算每個參數(shù)"調(diào)多少能讓 Loss 變小":
調(diào)整方向:讓 Loss 減小的方向(梯度下降)
W_Q 的某個數(shù)原來是 0.1
梯度告訴我們:這個數(shù)應(yīng)該增大一點,Loss 才會減小
→ 調(diào)整后變成 0.1 + 學習率 × 梯度 = 0.1 + 0.01 × 0.5 = 0.105
W_K、W_V 同理,每個數(shù)字都被微調(diào)一點點
這一次調(diào)整完,模型預測"魚"的概率可能從 75% 變成 76%。
第九步:重復幾千億次
換一條新的訓練數(shù)據(jù),重復第一步到第八步:
樣本1:"貓 喜歡" → 預測"魚" → 調(diào)整參數(shù)
樣本2:"我 吃" → 預測"飯" → 調(diào)整參數(shù)
樣本3:"天氣 很" → 預測"好" → 調(diào)整參數(shù)
...
重復幾千億次
每次調(diào)整都是微小的,但經(jīng)過幾千億次后:
W_Q 從隨機數(shù) → 變成"擅長提取查詢特征"的矩陣
W_K 從隨機數(shù) → 變成"擅長描述詞的特征"的矩陣
W_V 從隨機數(shù) → 變成"擅長攜帶語義內(nèi)容"的矩陣
訓練結(jié)束,推理期怎么用
訓練完 W_Q/W_K/W_V 就固定了。用戶輸入新句子時:
用戶輸入:"小明把球給了小紅,因為他"
1. 每個詞 → Embedding 向量
2. × 固定的 W_Q → Q(每個詞的"問卷")
3. × 固定的 W_K → K(每個詞的"名片")
4. × 固定的 W_V → V(每個詞的"內(nèi)容")
5. 計算 Attention 權(quán)重
→ "他"的 Q 和"小明"的 K 匹配度高
→ "他"的新向量融合大量"小明"信息
6. 預測下一個詞:"很"
7. 繼續(xù)生成,直到結(jié)束
W_Q/W_K/W_V 沒有變化,只是被"用"了一次。
一句話總結(jié)訓練過程
訓練 = 不斷喂數(shù)據(jù) → 預測 → 算誤差 → 微調(diào)參數(shù) → 重復
= 讓 W_Q/W_K/W_V 從一堆廢話隨機數(shù)
慢慢變成"懂語言"的參數(shù)矩陣
大模型的"參數(shù)"在例子里指什么
人們常說 GPT-3 有 1750 億參數(shù)、Claude 有幾百億參數(shù),這些參數(shù)就是上面例子里那些矩陣里的每一個數(shù)字。
回到我們的小例子,把所有矩陣展開數(shù)一數(shù):
Embedding 表(每個詞一個向量):
貓 → [1.0, 0.5] ← 2 個數(shù)
喜歡 → [0.3, 0.8] ← 2 個數(shù)
魚 → [0.9, 0.1] ← 2 個數(shù)
小計:3 個詞 × 2 維 = 6 個參數(shù)
W_Q 矩陣:
[[0.1, 0.2],
[0.3, 0.4]] ← 4 個數(shù) = 4 個參數(shù)
W_K 矩陣:
[[0.4, 0.1],
[0.2, 0.3]] ← 4 個參數(shù)
W_V 矩陣:
[[0.3, 0.5],
[0.1, 0.2]] ← 4 個參數(shù)
最后一層(輸出層,把向量變成詞的概率):
也是一個矩陣 ← 假設(shè) 6 個參數(shù)
────────────────────────────────
這個玩具模型總參數(shù)量 ≈ 6+4+4+4+6 = 24 個參數(shù)
這 24 個數(shù)字,就是這個玩具模型的全部"知識"。
訓練過程就是反復調(diào)整這 24 個數(shù)字,讓它們從隨機值變成能預測"貓 喜歡 → 魚"的值。
放大到真實大模型
真實模型和玩具模型的區(qū)別,只是數(shù)字的數(shù)量不同:
玩具模型(上面例子):
詞表 3 個詞,向量維度 2
→ 參數(shù)量:約 24 個
GPT-2(2019年):
詞表 50257 個詞,向量維度 768
Transformer 層數(shù) 12,每層有多個矩陣
→ 參數(shù)量:15 億個數(shù)字
GPT-3(2020年):
向量維度 12288,層數(shù) 96
→ 參數(shù)量:1750 億個數(shù)字
Claude Sonnet 4.6(現(xiàn)在):
→ 參數(shù)量:未公開,估計數(shù)百億
結(jié)構(gòu)完全一樣:Embedding 表 + N 層(W_Q/W_K/W_V + 其他矩陣)+ 輸出層。
只是維度更大、層數(shù)更多,參數(shù)量從 24 個變成了幾百億個。
參數(shù)里存的是什么
參數(shù)不是人寫進去的規(guī)則,是訓練出來的數(shù)字,但這些數(shù)字里隱含了語言知識:
W_Q/W_K/W_V 里的數(shù)字
→ 隱含了"什么詞應(yīng)該關(guān)注什么詞"的規(guī)律
→ 比如代詞傾向于關(guān)注前面的名詞
Embedding 表里的數(shù)字
→ 隱含了詞與詞之間的語義關(guān)系
→ "國王"和"王后"的向量距離,接近"男人"和"女人"的向量距離
輸出層矩陣里的數(shù)字
→ 隱含了"什么上下文后面跟什么詞"的概率規(guī)律
→ 看到"我餓了,想吃",下一個詞大概率是食物
所有這些"知識",都壓縮在這幾百億個浮點數(shù)里。
模型文件之所以幾十 GB,就是因為要存下這幾百億個數(shù)字。
這些數(shù)字如何和文字對應(yīng)起來?
分兩張表,串聯(lián)起來完成"文字 ? 數(shù)字"的轉(zhuǎn)換。
第一張表:詞表(Vocabulary)— 文字 → ID
這是一張固定的查找表,訓練前就確定好了,訓練期間不變:
詞表(Tokenizer 內(nèi)置):
ID 詞
───────────────
0 → [PAD] (填充符)
1 → [UNK] (未知詞)
2 → [BOS] (句子開始)
3 → [EOS] (句子結(jié)束)
4 → "貓"
5 → "喜歡"
6 → "魚"
7 → "我"
8 → "你"
...
50256 → "hello"
用戶輸入 "貓 喜歡 魚" 時:
Tokenizer 查這張表:
"貓" → ID 4
"喜歡" → ID 5
"魚" → ID 6
得到 ID 序列:[4, 5, 6]
這張表是人工構(gòu)建的(統(tǒng)計語料中的高頻詞/子詞),GPT 系列約有 50257 個詞,Claude 更多。
第二張表:Embedding 表 — ID → 向量
這是一張可訓練的矩陣,每一行對應(yīng)一個 ID 的向量:
Embedding 表(訓練過程中不斷調(diào)整):
ID 向量(2維示意,實際幾千維)
──────────────────────────────
0 → [0.00, 0.00] (PAD)
1 → [0.01, 0.02] (UNK)
2 → [0.11, 0.33] (BOS)
3 → [0.22, 0.44] (EOS)
4 → [1.00, 0.50] (貓)
5 → [0.30, 0.80] (喜歡)
6 → [0.90, 0.10] (魚)
...
ID 序列 [4, 5, 6] 查這張表:
ID 4 → [1.00, 0.50] (貓的向量)
ID 5 → [0.30, 0.80] (喜歡的向量)
ID 6 → [0.90, 0.10] (魚的向量)
這張表里的數(shù)字,就是參數(shù)的一部分,訓練時會不斷調(diào)整,讓語義相近的詞向量距離更近。
輸出時反向查表:向量 → 文字
模型生成下一個詞時,輸出的是詞表上每個 ID 的概率,再查回詞表:
輸出層計算結(jié)果(每個 ID 的概率):
ID 4(貓) → 5%
ID 5(喜歡) → 8%
ID 6(魚) → 80%
ID 7(我) → 3%
...
選概率最高的 → ID 6
查詞表 → ID 6 = "魚"
輸出文字 → "魚"
完整的文字 ? 數(shù)字流程
輸入側(cè):
文字 "貓 喜歡"
↓ 詞表(固定查找表)
ID 序列 [4, 5]
↓ Embedding 表(可訓練矩陣)
向量序列 [[1.0,0.5], [0.3,0.8]]
↓ Transformer(W_Q/W_K/W_V 等參數(shù))
新向量(融合了上下文)
輸出側(cè):
新向量
↓ 輸出層矩陣(可訓練參數(shù))
每個 ID 的概率 [5%, 8%, 80%, 3%, ...]
↓ 采樣/取最大值
ID 6
↓ 反查詞表(固定查找表)
文字 "魚"
兩張表的區(qū)別
| 詞表(Vocabulary) | Embedding 表 | |
|---|---|---|
| 內(nèi)容 | 文字 ? ID 的映射 | ID ? 向量的映射 |
| 大小 | 約 5~10 萬行 | 約 5~10 萬行 × 向量維度 |
| 是否可訓練 | 不變,訓練前固定 | 會變,訓練中不斷調(diào)整 |
| 存儲位置 | Tokenizer 文件里 | 模型參數(shù)文件里 |
| 作用 | 文字和數(shù)字的橋梁 | 讓數(shù)字攜帶語義信息 |
詞表是死的查找表,Embedding 表是活的參數(shù)矩陣。兩者配合,完成"文字→語義向量→文字"的完整轉(zhuǎn)換。
2.3 為什么叫"大"語言模型
參數(shù)量決定了模型的記憶和推理能力:
| 模型 | 參數(shù)量 | 能力水平 |
|---|---|---|
| GPT-2(2019) | 15 億 | 能寫連貫文章,推理較弱 |
| GPT-3(2020) | 1750 億 | 涌現(xiàn)出 few-shot 學習能力 |
| GPT-4(2023) | 未公開(估計萬億級) | 接近人類專家水平 |
| Claude 3.5 Sonnet | 未公開 | 頂級推理和代碼能力 |
涌現(xiàn)(Emergence):參數(shù)量超過某個閾值后,模型突然獲得之前沒有的能力。這不是線性增長,而是質(zhì)變。
三、訓練過程(知道即可)
3.1 預訓練
數(shù)據(jù)來源:互聯(lián)網(wǎng)文本、書籍、代碼、論文...
↓
任務(wù):給定前 N 個 Token,預測第 N+1 個 Token
↓
損失函數(shù):預測錯了就調(diào)整參數(shù)(梯度下降)
↓
重復數(shù)萬億次
↓
模型學會了語言規(guī)律、世界知識、推理模式
關(guān)鍵理解:預訓練完的模型是一個"知識壓縮器",把互聯(lián)網(wǎng)上的信息壓縮進了參數(shù)里。但它只會續(xù)寫文本,不會"對話"。
3.2 RLHF:讓模型變得有用
Reinforcement Learning from Human Feedback(人類反饋強化學習):
Step 1:監(jiān)督微調(diào)(SFT)
人類寫出"好的"對話示例
→ 模型學習如何回答問題
Step 2:獎勵模型訓練
人類對多個回答排序(A > B > C)
→ 訓練一個"評分模型"
Step 3:PPO 強化學習
用評分模型給 LLM 的回答打分
→ 強化好回答,懲罰壞回答
→ 模型越來越符合人類期望
這一步產(chǎn)生了"對齊":模型從"續(xù)寫機器"變成"樂于助人的助手"。
3.3 知識截止日期
模型的知識來自訓練數(shù)據(jù),訓練數(shù)據(jù)有截止時間:
Claude Sonnet 4.6 的知識截止:2025 年 8 月
→ 2025 年 8 月之后發(fā)生的事,模型不知道
→ 模型可能會"自信地"給出錯誤的新信息(幻覺)
工程含義:涉及實時信息的場景,必須通過 RAG 或工具調(diào)用補充最新知識。
四、推理過程:模型如何生成文字
4.1 自回歸生成
LLM 每次只生成一個 Token,然后把這個 Token 加入輸入,再生成下一個:
輸入:"今天天氣"
→ 模型預測下一個 Token:{"很": 0.6, "不": 0.2, "真": 0.1, ...}
→ 采樣選出"很"
→ 輸入變成"今天天氣很"
→ 模型預測:{"好": 0.5, "差": 0.3, "熱": 0.15, ...}
→ 采樣選出"好"
→ 輸入變成"今天天氣很好"
→ ...直到生成結(jié)束符
工程含義:
- 生成速度與輸出長度成正比,輸出越長越慢
- 流式輸出(Streaming)就是每生成一個 Token 就立刻返回
4.2 Temperature:控制隨機性
Temperature = 0 → 每次都選概率最高的 Token(確定性,適合代碼/數(shù)學)
Temperature = 0.7 → 適度隨機(平衡創(chuàng)意和準確,適合對話)
Temperature = 1.5 → 高度隨機(創(chuàng)意寫作,可能胡言亂語)
直覺:Temperature 越高,模型越"天馬行空";越低,越"保守準確"。
4.3 Context Window:模型的"工作記憶"
┌──────────────────────────────────────────────┐
│ Context Window │
│ │
│ System Prompt │ 歷史對話 │ 當前輸入 │ 輸出 │
│ (系統(tǒng)設(shè)定) │ │ │ │
└──────────────────────────────────────────────┘
↑
模型只能看到這個窗口內(nèi)的內(nèi)容
關(guān)鍵限制:
- 超出 Context Window 的內(nèi)容,模型完全看不到(不是變模糊,是徹底消失)
- Context Window 越大,計算成本越高,速度越慢
- 長文本處理時,模型對"中間"部分的注意力往往弱于"開頭"和"結(jié)尾"(Lost in the Middle 問題)
五、LLM 的能力邊界
5.1 LLM 擅長的事
| 能力 | 原因 | 典型場景 |
|---|---|---|
| 文本生成與改寫 | 訓練目標本身就是預測文本 | 寫作、翻譯、摘要 |
| 代碼生成 | 訓練數(shù)據(jù)包含大量代碼 | 寫函數(shù)、修 Bug、解釋代碼 |
| 模式識別與分類 | 見過大量樣本 | 情感分析、意圖識別 |
| 知識問答 | 壓縮了大量世界知識 | 百科問答、概念解釋 |
| 格式轉(zhuǎn)換 | 見過各種格式互轉(zhuǎn)的例子 | JSON?表格、Markdown?HTML |
| 少樣本學習(Few-shot) | 涌現(xiàn)能力 | 給幾個例子,模型舉一反三 |
| 推理(有限范圍) | CoT 能力 | 數(shù)學題、邏輯推理 |
5.2 LLM 不擅長的事(能力邊界)
① 精確計算
問:1234567 × 9876543 = ?
LLM 的做法:根據(jù)訓練數(shù)據(jù)中的"數(shù)字模式"猜一個看起來合理的數(shù)
→ 可能是錯的,而且模型說得很自信
正確做法:通過工具調(diào)用真正的計算器
原理:LLM 處理數(shù)字和處理文字一樣,都是 Token 預測,沒有真正的"計算"能力。
② 實時信息
問:今天比特幣價格是多少?
LLM 的做法:給出訓練截止日前的價格,或者編造一個
→ 必然是錯的
正確做法:工具調(diào)用實時 API
③ 精確記憶長文本
給模型一份 10 萬字的文檔,然后問文檔第 5000 行的第 3 個數(shù)字
→ 模型大概率回答錯誤
原理:"Lost in the Middle" —— 模型對上下文中間部分的注意力顯著弱于頭尾
④ 穩(wěn)定的邏輯推理鏈
簡單推理:模型能做
→ "如果 A > B,B > C,那么 A > C?" → 正確
復雜推理鏈:容易出錯
→ 多步驟、多條件的推理,錯誤會累積
→ 特別是反事實推理("如果歷史上沒有發(fā)生X,Y會怎樣")
⑤ 自我認知
問:你確定這個答案是對的嗎?
LLM 的問題:模型不知道自己"知道"什么,"不知道"什么
→ 可能對錯誤的答案表現(xiàn)出高度自信
→ 也可能對正確的答案表示懷疑
這就是"幻覺"的根源之一
⑥ 持久記憶
對話結(jié)束后,下次對話模型完全不記得你
→ 每次對話都從零開始
→ 需要工程手段(數(shù)據(jù)庫 + RAG)實現(xiàn)跨會話記憶
六、幻覺(Hallucination):最重要的工程挑戰(zhàn)
6.1 什么是幻覺
模型自信地給出錯誤信息,叫做幻覺。
典型例子:
問:愛因斯坦在哪所大學獲得博士學位?
錯誤回答(幻覺):"愛因斯坦在柏林洪堡大學獲得博士學位"(編造的)
正確答案:蘇黎世大學
更危險的幻覺:
問:引用幾篇關(guān)于 XXX 的論文
→ 模型可能給出看起來真實的論文標題、作者、期刊,但完全是編造的
6.2 幻覺的根本原因
LLM 的本質(zhì):預測下一個 Token 的概率分布
≠ 檢索真實事實
當模型"不知道"答案時:
→ 它不會說"我不知道"(這不是訓練的主要目標)
→ 它會生成一個"看起來合理"的答案(因為這是訓練的目標)
→ 這個"合理"但錯誤的答案 = 幻覺
6.3 減少幻覺的工程手段
| 手段 | 原理 | 適用場景 |
|---|---|---|
| RAG(檢索增強生成) | 先檢索真實文檔,再讓模型基于文檔回答 | 知識庫問答、文檔分析 |
| 工具調(diào)用(Tool Use) | 讓模型調(diào)用外部 API 獲取真實數(shù)據(jù) | 實時信息、精確計算 |
| 降低 Temperature | 減少隨機性,避免"發(fā)揮" | 需要準確性的場景 |
| 要求引用來源 | Prompt 中要求模型給出依據(jù) | 研究類、事實類問題 |
| 輸出驗證 | 用另一個模型或規(guī)則校驗輸出 | 高風險場景 |
| 思維鏈(CoT) | 讓模型"逐步思考",減少跳躍 | 推理類問題 |
七、Prompt 工程:如何"駕駛"LLM
7.1 模型如何理解 Prompt
完整的輸入結(jié)構(gòu):
┌─────────────────────────────────┐
│ System Prompt(系統(tǒng)提示) │ 定義模型角色、規(guī)則、約束
├─────────────────────────────────┤
│ Few-shot 示例(可選) │ 示范期望的輸入輸出格式
├─────────────────────────────────┤
│ User Message(用戶輸入) │ 當前任務(wù)描述
├─────────────────────────────────┤
│ Assistant Prefix(可選) │ 引導模型以特定方式開始回答
└─────────────────────────────────┘
7.2 高質(zhì)量 Prompt 的要素
① 角色設(shè)定
差:幫我寫代碼
好:你是一個有 10 年經(jīng)驗的 Python 后端工程師,
擅長寫可維護、有完善錯誤處理的生產(chǎn)級代碼。
② 上下文完整
差:這個函數(shù)有 Bug,幫我修
好:以下是一個 Python 函數(shù),輸入是用戶 ID(整數(shù)),
預期輸出是用戶名(字符串)。
當用戶不存在時應(yīng)該拋出 UserNotFoundError。
現(xiàn)在當輸入 -1 時會崩潰,幫我修復:
[代碼]
③ 輸出格式明確
差:分析一下這個需求
好:分析以下需求,用 JSON 格式輸出,包含字段:
- risks: 風險列表(數(shù)組)
- complexity: 復雜度(low/medium/high)
- estimatedDays: 估算工作日(整數(shù))
④ 思維鏈(Chain of Thought)
在 Prompt 末尾加:
"請一步步思考,展示你的推理過程"
→ 顯著提升復雜推理的準確性
→ 原理:迫使模型在 Token 層面"寫出"中間步驟,減少跳躍
7.3 Prompt 的常見陷阱
| 陷阱 | 現(xiàn)象 | 解決方法 |
|---|---|---|
| 指令沖突 | System Prompt 和 User 要求矛盾 | 明確優(yōu)先級,減少歧義 |
| 上下文污染 | 歷史對話影響當前回答 | 關(guān)鍵任務(wù)用新會話 |
| 負面指令無效 | "不要做X"往往不如"做Y" | 用正面指令替代負面指令 |
| 過長 Prompt 失效 | 指令太多,模型"忘記"部分指令 | 精簡核心指令,輔以示例 |
| 格式不穩(wěn)定 | 同樣 Prompt 輸出格式不一致 | 用 Few-shot 示例固定格式 |
八、RAG:給 LLM 接上外部知識庫
8.1 為什么需要 RAG
LLM 的知識:
? 截止訓練數(shù)據(jù)的時間點
? 你的公司內(nèi)部文檔
? 實時信息
? 超過 Context Window 的長文檔
RAG 解決:讓模型基于"當下檢索到的真實內(nèi)容"回答
8.2 RAG 工作流程
離線階段(建立知識庫):
文檔
↓ 切片(Chunking)
文檔片段(每段 200~500 Token)
↓ Embedding 模型
向量(每段文字變成一串數(shù)字,語義相近的向量距離近)
↓ 存入向量數(shù)據(jù)庫(Pinecone/Weaviate/pgvector)
在線階段(用戶查詢):
用戶問題
↓ Embedding 模型
問題向量
↓ 向量數(shù)據(jù)庫相似度檢索
最相關(guān)的 N 個文檔片段
↓ 拼入 Prompt
LLM 基于檢索到的內(nèi)容生成回答
8.3 RAG 的關(guān)鍵參數(shù)
| 參數(shù) | 含義 | 調(diào)優(yōu)方向 |
|---|---|---|
| Chunk Size | 每段文字的長度 | 太小丟失上下文,太大檢索精度低 |
| Top-K | 檢索幾個片段 | 太少信息不足,太多噪音增加 |
| Embedding 模型 | 把文字轉(zhuǎn)向量的模型 | 影響檢索精度,中文需專用模型 |
| 重排序(Rerank) | 對檢索結(jié)果二次排序 | 顯著提升檢索準確性 |
RAG小結(jié)
RAG = Retrieval-Augmented Generation
- Retrieval:檢索
- Augmented:增強
- Generation:生成
直譯:檢索增強生成。
RAG 是指先根據(jù)離線文檔查找出一些內(nèi)容,然后作為提示詞和用戶問題一起給llm?這樣做好處是啥?
? 是的,理解完全正確。用一張圖說清楚:
沒有 RAG:
用戶問題 → LLM → 回答
(LLM 只靠訓練時學到的知識,可能幻覺)
有 RAG:
用戶問題
↓
向量檢索(從你的文檔庫里找最相關(guān)的片段)
↓
組裝 Prompt:
"根據(jù)以下資料回答問題:
[檢索到的文檔片段]
用戶問題:XXXX"
↓
LLM → 回答
(基于真實文檔內(nèi)容,有據(jù)可查)
---
好處
1. 解決知識截止問題
LLM 訓練數(shù)據(jù)有截止日期,你的內(nèi)部文檔、最新資料它根本不知道。RAG 讓模型能"看到"這些內(nèi)容。
2. 減少幻覺
模型有參考資料時,傾向于基于資料回答,而不是自己發(fā)揮??梢赃M一步要求"只根據(jù)提供的資料回答,資料里沒有
的就說不知道"。
3. 可追溯
回答可以附上"來源:第X段",用戶可以去驗證原文,企業(yè)場景下非常重要。
4. 不需要重新訓練模型
更新知識庫只需要更新文檔,不需要重新訓練或微調(diào)模型,成本極低。
5. 控制回答范圍
客服機器人只回答產(chǎn)品相關(guān)問題,把產(chǎn)品文檔放進知識庫,模型自然只在這個范圍內(nèi)回答。
---
核心代價
檢索質(zhì)量決定回答質(zhì)量——如果檢索到的片段不相關(guān),模型的回答也會跑偏。所以 RAG 的難點不在
LLM,在怎么把文檔切好、檢索準。
九、Function Calling 協(xié)議:LLM 突破文本邊界的關(guān)鍵設(shè)計
9.1 為什么需要 Function Calling
LLM 有一個根本限制:它只能輸出文本。
LLM 的本質(zhì):
輸入:一段文字(Prompt)
輸出:一段文字(預測的下一個 Token 序列)
僅此而已。
這意味著:
- 它無法執(zhí)行代碼
- 它無法讀寫文件
- 它無法調(diào)用 API 獲取實時數(shù)據(jù)
- 它無法控制任何外部系統(tǒng)
如果沒有任何擴展,LLM 就是個"純文字生成機",用戶問"北京現(xiàn)在天氣怎樣",它只能靠訓練數(shù)據(jù)里的知識猜測一個合理的答案——幻覺不可避免。
Function Calling(函數(shù)調(diào)用)協(xié)議就是為了解決這個問題而誕生的:讓 LLM 在需要時,用文本的形式"聲明"它想調(diào)用某個函數(shù),再由外部代碼真正執(zhí)行,把結(jié)果反饋給模型。
9.2 協(xié)議的核心思想:LLM 輸出結(jié)構(gòu)化指令
關(guān)鍵洞察是:
LLM 雖然只能輸出文本,但文本可以是結(jié)構(gòu)化的(JSON)。
把 JSON 當成"指令",由外部程序解析并執(zhí)行,就相當于 LLM "調(diào)用"了外部功能。
傳統(tǒng)對話:
用戶問題 → LLM → 自然語言回答
Function Calling:
用戶問題 + 工具列表 → LLM → 結(jié)構(gòu)化調(diào)用指令(JSON)
↓
外部代碼解析并執(zhí)行
↓
執(zhí)行結(jié)果注入 Context
↓
LLM 讀取結(jié)果 → 生成最終回答
LLM 自己什么都沒有"執(zhí)行",它只是輸出了一段 JSON,外部系統(tǒng)幫它完成了真正的動作。
9.3 完整協(xié)議流程
以"查北京天氣"為例,走一遍完整的 Function Calling 協(xié)議:
第一步:開發(fā)者定義工具
在調(diào)用 LLM API 時,把可用工具的"說明書"傳給模型:
tools: [
{
"name": "get_weather",
"description": "獲取指定城市的實時天氣。當用戶詢問天氣信息時調(diào)用此工具。",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名稱,如'北京'、'上海'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "溫度單位,默認 celsius"
}
},
"required": ["city"]
}
}
]
關(guān)鍵點:description 是給 LLM 看的,模型根據(jù)這段文字決定"什么時候該調(diào)哪個工具"。寫得越準確,模型的判斷越正確。
第二步:LLM 決策——輸出調(diào)用指令
用戶問:"北京今天天氣怎么樣?"
LLM 的回應(yīng)不是自然語言,而是一段結(jié)構(gòu)化指令(以 Claude API 為例):
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {
"city": "北京",
"unit": "celsius"
}
}
這就是 LLM 輸出的"文本",只不過格式是 JSON。LLM 本身并沒有調(diào)用任何東西。
第三步:外部代碼執(zhí)行工具
你的代碼接收到這個 JSON,解析出函數(shù)名和參數(shù),真正去調(diào) API:
# 偽代碼
if response.type == "tool_use":
tool_name = response.name # "get_weather"
tool_input = response.input # {"city": "北京", "unit": "celsius"}
# 真正執(zhí)行 API 調(diào)用
result = call_weather_api(city="北京", unit="celsius")
# result = {"temp": 22, "unit": "celsius", "weather": "晴", "humidity": "45%"}
第四步:把結(jié)果注入 Context,再次調(diào)用 LLM
把工具執(zhí)行結(jié)果寫入對話歷史,重新發(fā)給 LLM:
messages: [
{"role": "user", "content": "北京今天天氣怎么樣?"},
{"role": "assistant", "content": [{"type": "tool_use", "name": "get_weather", ...}]},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "{\"temp\": 22, \"weather\": \"晴\", \"humidity\": \"45%\"}"
}
]
}
]
第五步:LLM 基于真實數(shù)據(jù)生成回答
LLM 讀取到工具返回的結(jié)果,生成最終自然語言回答:
"北京今天天氣晴朗,氣溫 22°C,濕度 45%,出門不需要帶傘。"
這次回答有真實數(shù)據(jù)支撐,不是幻覺。
整個流程圖
用戶:"北京今天天氣怎么樣?"
↓
[LLM] 讀取:用戶問題 + 工具列表
↓
[LLM] 輸出:{"type":"tool_use","name":"get_weather","input":{"city":"北京"}}
↓ (LLM 只輸出了這段文字)
[外部代碼] 解析 JSON,真正調(diào)用天氣 API
↓
[外部代碼] 把結(jié)果 {"temp":22,"weather":"晴"} 注入 Context
↓
[LLM] 讀取真實數(shù)據(jù),生成自然語言回答
↓
"北京今天晴,22°C"
9.4 LLM 如何"決定"調(diào)不調(diào)工具
LLM 并沒有專門的"決策模塊",它的決策機制和生成文字完全一樣:預測下一個 Token。
訓練時,Anthropic / OpenAI 給模型大量"什么時候該調(diào)工具"的示例數(shù)據(jù),模型學會了:
Context 里有工具列表 + 用戶問實時信息
→ 下一個 Token 大概率是 {"type":"tool_use"...}
Context 里有工具列表 + 用戶問一般知識
→ 下一個 Token 大概率是自然語言回答
本質(zhì)上,LLM 只是在"續(xù)寫"一段包含工具調(diào)用格式的對話,和寫普通文字沒有區(qū)別。
9.5 多工具串聯(lián):一次任務(wù),多次調(diào)用
Function Calling 的真正威力在于多工具串聯(lián):LLM 可以連續(xù)調(diào)用多個工具,每次把上一步的結(jié)果作為下一步的輸入。
用戶:"幫我查一下北京和上海的天氣,然后推薦周末去哪個城市旅游。"
第一輪:
LLM 輸出:調(diào)用 get_weather(city="北京")
外部執(zhí)行:返回北京天氣數(shù)據(jù)
第二輪(結(jié)果注入 Context):
LLM 輸出:調(diào)用 get_weather(city="上海")
外部執(zhí)行:返回上海天氣數(shù)據(jù)
第三輪(兩個結(jié)果都在 Context 里):
LLM 綜合兩個城市的數(shù)據(jù),生成推薦:
"上海周末晴天 24°C,北京有輕度霧霾,建議去上海。"
這種模式,就是 AI Agent 的雛形——LLM 自主規(guī)劃多個步驟,逐步完成目標。
9.6 工程注意事項
| 注意點 | 說明 |
|---|---|
| description 寫清楚 | 模型根據(jù) description 決定是否調(diào)用;描述模糊會導致誤調(diào)用或漏調(diào)用 |
| 工具數(shù)量適中 | 工具越多,模型"選錯"的概率越高;單次對話建議不超過 20 個 |
| 做好錯誤處理 | 工具調(diào)用可能失?。ňW(wǎng)絡(luò)超時等),要有 fallback,不能讓整個對話掛起 |
| 危險操作加人工確認 | 刪除、支付、發(fā)送郵件等不可逆操作,不能由模型直接觸發(fā) |
| 工具結(jié)果控制大小 | 工具返回內(nèi)容太長會占滿 Context Window,要提前裁剪或摘要 |
| 冪等性 | 工具可能被重復調(diào)用(模型重試),設(shè)計時考慮冪等性 |
9.7 Function Calling 是 AI Agent 的基石
沒有 Function Calling,LLM 永遠困在文字的世界里。
有了 Function Calling,LLM 可以:
- 查詢實時數(shù)據(jù)(不再幻覺)
- 寫入文件、執(zhí)行命令(從"說"到"做")
- 調(diào)用任意 API(連接整個互聯(lián)網(wǎng))
- 串聯(lián)多步驟工具調(diào)用(完成復雜任務(wù))
這正是下一章 AI Agent 的技術(shù)基礎(chǔ):Agent = LLM 大腦 + Function Calling 協(xié)議 + 外部工具集合。
十、LLM 的成本與速度
10.1 計費模型
主流 LLM API 按 Token 計費:
費用 = 輸入 Token 數(shù) × 輸入單價 + 輸出 Token 數(shù) × 輸出單價
Claude Sonnet 4.6(參考價):
輸入:$3 / 百萬 Token
輸出:$15 / 百萬 Token
一次對話(1000 輸入 + 500 輸出):
費用 = 1000/1,000,000 × $3 + 500/1,000,000 × $15
= $0.003 + $0.0075
= $0.0105 ≈ 約 7 分錢人民幣
輸出比輸入貴:因為輸出是自回歸逐個生成,計算量更大。
10.2 速度瓶頸
影響響應(yīng)速度的因素:
TTFT(首 Token 時間)
= 處理輸入 Token 的時間
→ 輸入越長,TTFT 越長
TPS(每秒輸出 Token 數(shù))
= 模型生成速度
→ 通常 50~100 Token/秒
→ 輸出 1000 Token ≈ 10~20 秒
總延遲 = TTFT + 輸出 Token 數(shù) / TPS
10.3 降低成本和延遲的工程手段
| 手段 | 效果 | 代價 |
|---|---|---|
| 使用小模型 | 成本降低 10x,速度提升 5x | 能力下降 |
| 縮短 Prompt | 減少輸入 Token | 可能降低質(zhì)量 |
| 限制輸出長度(max_tokens) | 控制輸出成本 | 可能截斷 |
| 緩存(Prompt Cache) | 相同前綴只計算一次 | 需要管理緩存 |
| 流式輸出(Streaming) | 用戶感知延遲降低 | 處理復雜度增加 |
| 批處理(Batching) | 吞吐量提升 | 響應(yīng)延遲增加 |
十一、多模態(tài):超越文字
11.1 現(xiàn)狀
主流 LLM 已支持多種模態(tài)輸入:
| 模態(tài) | 代表模型 | 典型用途 |
|---|---|---|
| 文字 → 文字 | 所有 LLM | 對話、寫作、代碼 |
| 圖片 → 文字 | GPT-4o, Claude 3.5 | 圖片描述、OCR、圖表分析 |
| 文字 → 圖片 | DALL-E, Midjourney | 圖片生成 |
| 語音 → 文字 | Whisper | 語音轉(zhuǎn)錄 |
| 文字 → 語音 | ElevenLabs, TTS | 語音合成 |
| 視頻 → 文字 | Gemini 1.5 Pro | 視頻理解 |
11.2 工程含義
- 圖片處理比文字貴:一張圖片通常消耗 1000~2000 Token
- 不同模態(tài)有不同的能力邊界:模型看圖的能力遠弱于讀文字
- 多模態(tài)輸入需要特殊的 API 格式(base64 編碼或 URL)
十二、AI Agent:讓 LLM 從"問答"變成"行動"
以下分析基于兩個有源碼依據(jù)的真實系統(tǒng):Claude Code(Anthropic 官方 CLI)和 OpenClaw(開源個人 AI 助手)。
12.1 什么是 AI Agent
純 LLM 是一個"問答機器":輸入 → 輸出,一問一答,不能主動做事。
AI Agent 在 LLM 之上加了一個執(zhí)行循環(huán),讓模型可以:
用戶目標
↓
[Agent Loop 循環(huán)執(zhí)行]
├── 思考:現(xiàn)在應(yīng)該做什么? ← LLM 負責
├── 行動:調(diào)用工具(讀文件/搜索/寫代碼/執(zhí)行命令)← 外部工具執(zhí)行
├── 觀察:工具返回了什么結(jié)果? ← 結(jié)果注入 Context 給 LLM
└── 判斷:目標完成了嗎?→ 沒有 → 繼續(xù)循環(huán) ← LLM 負責
↓
目標達成,輸出結(jié)果
核心差異:
| 純 LLM | AI Agent | |
|---|---|---|
| 交互方式 | 一問一答 | 自主多步執(zhí)行 |
| 工具使用 | 無 | 可調(diào)用外部工具 |
| 狀態(tài)保持 | 無(單次對話) | 有(跨步驟記憶) |
| 主動性 | 被動響應(yīng) | 可主動規(guī)劃和執(zhí)行 |
12.2 LLM 在 Agent 中扮演的角色
Agent 系統(tǒng)中 LLM 是大腦,工具是四肢,兩者缺一不可。
┌──────────────────────────────────────────────────────┐
│ Agent 系統(tǒng) │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ LLM(大腦) │ │
│ │ │ │
│ │ ① 理解用戶意圖 │ │
│ │ "幫我重構(gòu)這個函數(shù)" → 拆解成具體步驟 │ │
│ │ │ │
│ │ ② 決策:下一步調(diào)用哪個工具?參數(shù)是什么? │ │
│ │ → 輸出 Function Call 指令 │ │
│ │ │ │
│ │ ③ 解讀工具結(jié)果 │ │
│ │ → 工具返回文件內(nèi)容,LLM 理解并繼續(xù)規(guī)劃 │ │
│ │ │ │
│ │ ④ 判斷任務(wù)是否完成 │ │
│ │ → 生成最終回答或繼續(xù)下一輪循環(huán) │ │
│ └──────────────────────────────────────────────┘ │
│ ? Function Call / Tool Result │
│ ┌──────────────────────────────────────────────┐ │
│ │ 工具層(四肢) │ │
│ │ │ │
│ │ 讀文件 / 寫文件 / 執(zhí)行命令 / 搜索 / 調(diào) API │ │
│ │ LLM 本身無法做這些,必須通過工具完成 │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
LLM 具體負責哪些決策:
| Agent 階段 | LLM 做的事 | 工具做的事 |
|---|---|---|
| 意圖理解 | 把自然語言拆解成可執(zhí)行計劃 | 無 |
| 工具選擇 | 決定調(diào)用哪個工具、傳什么參數(shù) | 無 |
| 工具執(zhí)行 | 無 | 實際執(zhí)行(讀寫文件、命令等) |
| 結(jié)果解讀 | 理解工具返回的內(nèi)容,判斷下一步 | 無 |
| 錯誤處理 | 工具失敗時決定重試還是換方案 | 無 |
| 任務(wù)完成判斷 | 判斷目標是否達成 | 無 |
關(guān)鍵理解:LLM 每次只處理當前 Context 內(nèi)的信息,它看不到"過去的步驟",只能看到被注入 Context 的工具結(jié)果。Agent 框架的核心工作之一就是把每步的工具結(jié)果正確地寫入 Context,讓 LLM 能"記住"已經(jīng)做過什么。
12.3 案例一:Claude Code
依據(jù):
CLAUDE_CODE_ARCHITECTURE.md(基于官方 CLI 架構(gòu)分析)
是什么
Claude Code 是 Anthropic 官方的命令行 AI 編程助手,采用工具增強的 Agent 架構(gòu),在本地運行,直接操作你的代碼倉庫。
核心架構(gòu)
用戶輸入(自然語言)
↓
┌─────────────────────────────────────────┐
│ Claude Code Core │
│ │
│ 會話管理器 → 維護對話歷史和上下文 │
│ 權(quán)限控制器 → 控制哪些工具可以執(zhí)行 │
│ 上下文管理器 → 識別工作目錄/Git狀態(tài) │
│ 記憶系統(tǒng) → CLAUDE.md + Auto Memory │
└──────────────────┬──────────────────────┘
↓
┌──────────────────────────────────────────┐
│ Agent 執(zhí)行引擎(Agent Loop) │
│ │
│ 思考 → 規(guī)劃 → 執(zhí)行 → 反思 → 迭代 │
│ │
│ 子 Agent 管理: │
│ Explore Agent → 探索代碼庫 │
│ Plan Agent → 制定實現(xiàn)計劃 │
│ Bash Agent → 執(zhí)行 Shell 命令 │
│ General Purpose → 通用任務(wù) │
└──────────────────┬──────────────────────┘
↓
┌──────────────────────────────────────────┐
│ 工具管理器(34+ 個工具) │
│ │
│ 本地工具:Read/Write/Edit/Bash/Glob/Grep │
│ MCP 工具:動態(tài)加載外部 MCP Server 工具 │
│ 子 Agent 工具:派發(fā)子任務(wù) │
└──────────────────────────────────────────┘
LLM 在 Claude Code 中的作用
Claude Code 使用 Claude 模型作為唯一的大腦,所有決策都由它完成:
用戶說:"幫我把這個函數(shù)改成異步的"
↓
LLM 接收到:System Prompt(角色設(shè)定)
+ CLAUDE.md(項目規(guī)范記憶)
+ Git 狀態(tài)(當前工作目錄上下文)
+ 用戶指令
LLM 決策輸出(Function Call):
→ 先調(diào)用 Read 工具讀取目標文件
↓ 文件內(nèi)容注入 Context
→ LLM 理解代碼結(jié)構(gòu),規(guī)劃修改方案
→ 調(diào)用 Edit 工具寫入修改
↓ 修改結(jié)果注入 Context
→ LLM 判斷:是否需要同步修改調(diào)用方?
→ 調(diào)用 Grep 搜索所有調(diào)用處
↓ 搜索結(jié)果注入 Context
→ LLM 決策:逐一修改調(diào)用處
→ 調(diào)用 Bash 運行測試驗證
↓ 測試結(jié)果注入 Context
→ LLM 判斷:測試通過,任務(wù)完成
LLM 在每一步的角色:理解當前狀態(tài) → 決定下一步工具調(diào)用 → 解讀結(jié)果 → 繼續(xù)或結(jié)束。
Claude Code 能做什么
? 能做
──────────────────────────────────────────
讀取、編寫、編輯本地文件(Read/Write/Edit)
搜索代碼庫(Glob/Grep)
執(zhí)行 Shell 命令(Bash)
Git 操作(status/diff/commit/push)
多文件聯(lián)動修改(理解跨文件依賴)
派發(fā)子 Agent 并行處理子任務(wù)
調(diào)用 MCP Server 擴展工具能力
通過 CLAUDE.md 記憶項目規(guī)范
Hooks 機制:工具執(zhí)行前后觸發(fā)自定義腳本
?? 有限制
──────────────────────────────────────────
不能訪問互聯(lián)網(wǎng)(除非配置了聯(lián)網(wǎng) MCP Server)
長任務(wù)中 Context Window 可能耗盡(需要手動壓縮)
復雜架構(gòu)決策仍需人工判斷
跨會話不自動記憶(需要 CLAUDE.md 顯式記錄)
? 不能做
──────────────────────────────────────────
運行圖形界面程序
實時監(jiān)聽文件變化(被動觸發(fā))
自主部署到生產(chǎn)環(huán)境(需要人工確認)
理解二進制文件內(nèi)容
權(quán)限控制機制
Claude Code 的關(guān)鍵設(shè)計是權(quán)限分級,不是所有操作都自動執(zhí)行:
工具調(diào)用權(quán)限等級:
自動執(zhí)行(無需確認):
→ Read(讀文件)
→ Glob(文件搜索)
→ Grep(內(nèi)容搜索)
需要用戶確認:
→ Write/Edit(寫文件)
→ Bash(執(zhí)行命令)
→ 網(wǎng)絡(luò)請求
永遠需要確認:
→ 危險命令(rm -rf、git push --force)
→ 生產(chǎn)環(huán)境操作
12.4 案例二:OpenClaw
依據(jù):
openclaw_architecture.md(基于源碼openclaw-main分析)
是什么
OpenClaw 是開源的個人 AI 助手網(wǎng)關(guān),核心理念:
你在哪里聊天,AI 就在哪里。
把 Claude/GPT/Gemini 等 AI 接入 WhatsApp、Telegram、Slack、Discord、iMessage 等日常 IM 工具,在用戶自己的設(shè)備上運行,數(shù)據(jù)不經(jīng)第三方。
核心架構(gòu)
IM 平臺(Telegram/Discord/Slack...)
↓ Webhook / Bot API / 長連接
┌─────────────────────────────────────┐
│ OpenClaw Gateway │
│ (運行在用戶本地設(shè)備) │
│ │
│ 接入層 → 消息規(guī)范化為 MsgContext │
│ 路由層 → 7級優(yōu)先級匹配 → agentId │
│ 調(diào)度層 → HTTP/WS服務(wù)、認證、Cron │
│ Agent層 → 會話管理、Prompt構(gòu)建 │
│ → Tool調(diào)用循環(huán)、流式輸出 │
│ 插件層 → Memory/Canvas/聯(lián)網(wǎng)搜索 │
│ Provider層→ 多模型統(tǒng)一封裝+Failover │
└──────────────┬──────────────────────┘
↓ API 調(diào)用
外部 AI 模型(Claude/GPT/Gemini/本地Ollama)
LLM 在 OpenClaw 中的作用
OpenClaw 支持多個 LLM Provider(Claude/GPT/Gemini/本地 Ollama),LLM 是可替換的"引擎":
Telegram 用戶:"幫我搜一下今天的 AI 新聞并總結(jié)"
↓
OpenClaw 流程:
接入層 → 消息規(guī)范化為 MsgContext
路由層 → 匹配到 agentId="default"
Agent層 → 加載會話歷史 + 構(gòu)建 Prompt:
System Prompt(人設(shè))
+ Memory 技能注入(長期記憶)
+ 會話歷史(短期記憶)
+ 可用工具列表(Web Search 等)
+ 用戶消息
LLM 決策:需要調(diào)用 Web Search 工具
↓ Function Call 輸出
Web Search 工具執(zhí)行 → 返回新聞內(nèi)容
↓ 結(jié)果注入 Context
LLM 生成摘要回答
↓ 流式輸出
發(fā)回 Telegram 用戶
LLM 在各層的具體角色:
接入層 → 與 LLM 無關(guān),純消息格式轉(zhuǎn)換
路由層 → 與 LLM 無關(guān),規(guī)則匹配
調(diào)度層 → 與 LLM 無關(guān),網(wǎng)絡(luò)服務(wù)
↓
Agent 層 ← LLM 在這里介入,是唯一的決策者
│
├── Prompt 構(gòu)建完成后 → 發(fā)給 LLM
│ LLM 讀?。合到y(tǒng)人設(shè) + 歷史對話 + 工具列表 + 用戶消息
│
├── LLM 輸出①:普通文本回復
│ → 直接流式發(fā)回用戶
│
└── LLM 輸出②:Function Call(工具調(diào)用指令)
→ Agent 層解析,執(zhí)行對應(yīng)工具
→ 工具結(jié)果寫回 Context
→ 再次調(diào)用 LLM,繼續(xù)決策
→ 循環(huán)直到 LLM 不再發(fā)出 Function Call
Provider 層 → 封裝各家 LLM 的 API 差異,LLM 對 Agent 層透明
LLM 在 OpenClaw 中的三個核心角色:
| 角色 | 具體表現(xiàn) |
|---|---|
| 對話者 | 理解用戶自然語言,生成自然語言回復 |
| 工具調(diào)度員 | 決定何時調(diào)用哪個工具(Web Search/Code Run 等),生成 Function Call 指令 |
| 內(nèi)容生成器 | 基于工具返回的真實數(shù)據(jù),組織成最終回答發(fā)給用戶 |
OpenClaw 中 LLM 的特殊點:
- 可熱切換:主模型失敗時 Failover 自動換備用模型,LLM 對 Agent 層透明
- 多 Agent 差異化配置:不同 agentId 可配置不同 LLM(如個人助手用 Claude Opus,編程助手用 Claude Sonnet)
- 本地模型可選:隱私場景可換成 Ollama 本地運行,LLM 推理完全在用戶設(shè)備上,零數(shù)據(jù)出網(wǎng)
- 流式輸出:LLM 每生成一個 Token 就立即推送給 IM 平臺,用戶看到逐字輸出效果
OpenClaw 能做什么
? 能做
──────────────────────────────────────────
接入 10+ 個 IM 平臺(Telegram/Discord/Slack/
WhatsApp/iMessage/Signal/飛書/Matrix...)
多 Agent 路由:不同用戶/群組路由到不同 Agent
跨會話記憶(Memory 技能)
聯(lián)網(wǎng)搜索(Web Search 技能)
代碼執(zhí)行(Code Run 技能,沙箱環(huán)境)
Webhook 集成(外部系統(tǒng)注入消息)
Cron 定時任務(wù)(定時觸發(fā) Agent)
多模型自動故障轉(zhuǎn)移(Failover)
本地模型支持(Ollama,數(shù)據(jù)不出網(wǎng))
語音對話(Voice Call 技能)
插件擴展(自定義通道/工具/技能)
?? 有限制
──────────────────────────────────────────
記憶依賴 Memory 技能,默認不持久化
聯(lián)網(wǎng)能力依賴 Web Search 插件,非內(nèi)置
跨平臺會話默認隔離(需配置共享)
代碼執(zhí)行在沙箱內(nèi),無法訪問宿主文件系統(tǒng)
? 不能做
──────────────────────────────────────────
直接操作用戶設(shè)備的文件系統(tǒng)(設(shè)計如此)
訪問 IM 平臺的歷史消息(只能接收新消息)
主動發(fā)起 IM 會話(只能被動響應(yīng))
實時感知用戶上線狀態(tài)
OpenClaw 的路由機制(7 級優(yōu)先級)
來自源碼分析:
消息進來時,按優(yōu)先級從高到低匹配 Binding 規(guī)則:
1. binding.peer → 精確匹配特定用戶/群組(最高優(yōu)先)
2. binding.peer.parent → 匹配線程父級
3. binding.guild+roles → Discord 服務(wù)器 + 角色組合
4. binding.guild → 整個 Discord 服務(wù)器
5. binding.team → Slack 工作區(qū)
6. binding.account → 賬號級別
7. binding.channel → 通道通配符(最低優(yōu)先)
default → 默認 Agent(兜底)
12.5 兩者對比
| Claude Code | OpenClaw | |
|---|---|---|
| 定位 | 編程助手(操作代碼) | 個人助手網(wǎng)關(guān)(多平臺接入) |
| 運行環(huán)境 | 終端命令行 | 本地后臺服務(wù) |
| 核心能力 | 讀寫文件、執(zhí)行命令、Git | 多平臺消息路由、AI 對話 |
| 工具來源 | 內(nèi)置34+工具 + MCP Server | 插件系統(tǒng)(通道/技能/Provider) |
| 記憶機制 | CLAUDE.md + Auto Memory | 會話 JSONL + Memory 技能 |
| 多模型 | 單模型(Claude) | 多模型 + Failover |
| 數(shù)據(jù)隱私 | 本地運行,代碼不上傳 | 本地運行,數(shù)據(jù)不經(jīng)第三方 |
| 擴展方式 | MCP Server | Plugin SDK(npm 包) |
| 適合場景 | 軟件開發(fā)、代碼任務(wù) | 日常助手、自動化、多平臺 |
12.6 AI Agent 的通用能力邊界
無論哪種 Agent 系統(tǒng),以下是共同的能力邊界:
? Agent 比純 LLM 強的地方
──────────────────────────────────────────
可以執(zhí)行多步驟任務(wù),不需要用戶每步都參與
可以調(diào)用真實工具(文件、命令、API)
可以基于中間結(jié)果調(diào)整計劃
可以并行派發(fā)子任務(wù)提高效率
可以跨會話保持記憶(需要顯式設(shè)計)
?? Agent 的固有限制
──────────────────────────────────────────
每一步仍然依賴 LLM 的推理質(zhì)量
工具調(diào)用失敗會導致任務(wù)中斷(需要容錯設(shè)計)
長任務(wù)會消耗大量 Context Window
自主執(zhí)行有風險:錯誤操作難以撤回
調(diào)試困難:多步驟執(zhí)行鏈路難以追蹤
? Agent 做不到的事
──────────────────────────────────────────
真正的"理解"(仍是模式匹配)
100% 可靠的自主執(zhí)行(必須有人工監(jiān)督機制)
超出工具邊界的操作(工具沒給的能力,Agent 沒有)
實時感知外部世界變化(被動觸發(fā),非主動監(jiān)聽)
12.7 Agent 系統(tǒng)設(shè)計的關(guān)鍵原則
原則一:Human-in-the-loop(人在回路)
高風險操作必須人工確認,Claude Code 的權(quán)限分級就是最好的實踐。Agent 越自主,需要越嚴格的確認機制。
原則二:工具邊界即能力邊界
Agent 能做的事,完全由給它的工具決定。設(shè)計 Agent 系統(tǒng) = 設(shè)計工具集合 + 設(shè)計工具的權(quán)限邊界。
原則三:失敗是常態(tài),容錯是必須
工具調(diào)用失敗率在生產(chǎn)環(huán)境中不可忽視,需要:重試機制、降級策略、人工介入觸發(fā)點。
原則四:Context 是稀缺資源
長任務(wù)中 Context Window 會耗盡,需要主動壓縮歷史、提煉關(guān)鍵信息,而不是等到溢出再處理。
十三、能力邊界速查表
? LLM 做得好
──────────────────────────────────────────
文本生成、改寫、摘要、翻譯
代碼生成、解釋、重構(gòu)
分類、情感分析、意圖識別
結(jié)構(gòu)化提?。◤奈淖种刑崛?JSON)
問答(基于提供的上下文)
頭腦風暴、創(chuàng)意寫作
格式轉(zhuǎn)換
?? LLM 能做但要小心
──────────────────────────────────────────
數(shù)學推理(簡單可以,復雜容易出錯 → 用工具)
事實問答(可能幻覺 → 用 RAG + 要求引用)
長文檔理解(中間部分注意力弱 → 分段處理)
復雜邏輯推理(多步驟 → 用 CoT)
代碼調(diào)試(簡單 Bug 可以,復雜系統(tǒng)問題不行)
? LLM 做不好
──────────────────────────────────────────
精確計算(→ 調(diào)用計算器工具)
實時信息(→ 調(diào)用 API)
持久記憶(→ 數(shù)據(jù)庫 + RAG)
確定性輸出(同樣輸入可能不同輸出)
超長文檔逐字檢索
真正的"理解"(模型是模式匹配,不是真正理解)
十三、常見誤解糾正
| 誤解 | 真相 |
|---|---|
| "LLM 有意識/情感" | 沒有。只是復雜的統(tǒng)計模式匹配 |
| "LLM 在搜索互聯(lián)網(wǎng)" | 沒有。知識在參數(shù)里,截止于訓練日期(除非有工具) |
| "LLM 每次回答一樣" | 不是。有隨機性(Temperature),同樣問題可能不同答案 |
| "更長的 Prompt 一定更好" | 不是。太長可能稀釋關(guān)鍵指令,"Lost in the Middle" |
| "LLM 知道自己不知道什么" | 不知道。這是幻覺的根源 |
| "GPT-4 比 GPT-3.5 在所有任務(wù)都強" | 不一定。大模型在某些簡單任務(wù)反而更慢更貴,不必然更準 |
| "Fine-tuning 能解決所有問題" | 不是。微調(diào)改變行為風格,RAG 才能注入新知識 |
十四、總結(jié):工程師需要記住的核心認知
1. LLM 是"概率續(xù)寫機器",不是"知識檢索系統(tǒng)"
→ 會幻覺,需要 RAG 和工具調(diào)用來補充
2. Context Window 是硬限制
→ 超出即"失憶",設(shè)計時必須考慮
3. Token 是一切的基本單位
→ 成本、速度、長度限制都以 Token 計算
4. Temperature 控制隨機性
→ 準確性要求高 → 低 Temperature
→ 創(chuàng)意要求高 → 高 Temperature
5. 幻覺是模型的固有特性,不是 Bug
→ 必須在系統(tǒng)層面設(shè)計驗證機制
6. 工具調(diào)用是補充能力邊界的正確方式
→ 計算用計算器,實時信息用 API,存儲用數(shù)據(jù)庫
7. Prompt 是"編程語言"
→ 清晰、具體、有示例的 Prompt 產(chǎn)生更好的輸出
8. 能力在快速進化,邊界在持續(xù)擴展
→ 今天做不好的事,3 個月后可能就能做好
→ 持續(xù)跟蹤模型更新
本文檔寫于 2026 年,基于當前主流 LLM(Claude、GPT-4o、Gemini)的實際工程經(jīng)驗。