Chapter 1 · 把 LLM 当作概率分布生成器
在动手之前必须先承认一个事实:LLM 不是数据库,也不是程序员,它是一个根据上下文输出 token 概率分布的函数。本部分解决的不是技术问题,而是心智模型问题——只有把 LLM 看清楚了,后面四个部分讲的工程手段才不会被你滥用。
LLM 看上去像是在"思考"、像是在"回忆事实"、像是在"推理",但所有这些感觉都是它在做一件事的副作用——给定前缀,对下一个 token 输出一个概率分布。所有的失败模式,最终都可以在这个简单事实上找到根源。本章用三条最基础的 Item 帮助你把直觉搬到正确的轨道上。
Item 1:区分"概率"与"知识"——LLM 不是数据库
把 LLM 想象成一个被 95% 互联网内容洗过脑的老烟枪——他熟悉的话题能侃侃而谈,他没见过的就会一本正经地胡说,而你无法仅从语气判断他是哪一类。
引子
工程师初学 LLM 时常犯的错误是这样的:
> 用户:"请告诉我我们公司 2025 年 Q3 财报的净利润。"
> 模型:"根据您 2025 Q3 财报,净利润为 $4.21 亿,同比增长 18.6%……"数字看着很专业,方差到了小数点后一位。但模型从未见过这份财报。它只是在概率分布里给"$4.21 亿"分配了较高的 logit,因为这种长度、这种格式的回答在训练数据里很常见。
机制原理
LLM 的本质是一个条件概率——给定已有文本,预测下一个 token 的概率分布。它不存储"哪条事实是真的"——它存储的是"在这种前缀下,大家通常说什么"。自信和正确是两件事——RLHF 后这两件事的相关性反而被削弱了(详见 Just Ask for Calibration,arXiv:2305.14975)。这就是为什么模型可以一边声称 100% 确定,一边给出错误的数字。
反例 vs 正例
# Bad — 把 LLM 当数据库
answer = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "我们公司 2025 Q3 净利润是多少?"}],
).choices[0].message.content
print(answer) # 信了就完蛋
# Good — 把 LLM 当"读文档的人"
docs = retrieve_from_internal_finance_db(query="2025 Q3 net income")
answer = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": "仅基于以下 <context> 回答;如无答案则说 '未找到';"
"每条数字必须标注来源 [n]。",
}, {
"role": "user",
"content": f"<context>\n{docs}\n</context>\n\n问题:我们公司 2025 Q3 净利润是多少?",
}],
).choices[0].message.contentThings to Remember
- LLM 的输出是概率分布上的一次采样,不是对事实的查询。
- "听起来自信" ≠ "正确"——RLHF 削弱了 token 概率与正确率的相关性。
- 凡是涉及私有数据 / 时效信息 / 精确数值的回答,必须绑定外部确定性系统(RAG / Tool / DB)。
延伸阅读
- Just Ask for Calibration(arXiv:2305.14975)—— 让模型直接说出 0-100% 的信心分数,比读取它内部的 token 概率更接近真实正确率;RLHF 把模型的概率分布搞歪了。
- Hallucination Survey(arXiv:2311.05232)—— LLM 幻觉的系统综述:从数据、训练、推理三个阶段梳理成因,并归纳检测与缓解方法。
- Retrieval-Augmented Generation for Knowledge-Intensive NLP(arXiv:2005.11401)—— RAG 的开山之作:首次把"检索 + 生成"做成端到端可训练架构,奠定后续所有 RAG 系统的范式。
Item 2:把"看似确定的输出"视为一次采样
你看见的不是模型的"答案",而是它这一次的答案。
核心
同一个 prompt 跑两遍,结果可能不同——尤其是 temperature > 0 时。即便 temperature = 0(贪婪解码),实际推理也很难保证完全可复现:
- 开源模型本地推理:浮点累加顺序、batch 大小、CUDA kernel 调度都会引入扰动;想要严格复现需固定硬件、
batch_size=1、关闭 continuous batching、开启 deterministic kernel——生产服务通常做不到。 - 闭源 API:除上述因素外,还有模型热更新、集群路由、AB 分流等用户不可见的变量,
seed参数也只是 best effort。
不要基于一次输出做产品决策——尤其是评估阶段。
Things to Remember
- 任何"我跑了一次它对了"的结论都不算证据,依据中心极限定理,至少要跑 30 次统计成功率才作数。
- 评估时必须固定
temperature和seed,并把 model version + 日期写进 log。 - 多采样投票(Self-Consistency)是 80/20 的鲁棒性提升——见 Self-Consistency Improves CoT(arXiv:2203.11171)。
Item 3:用 temperature / top_p / seed 控制采样,而不是用 prompt 控制"思考"
让 prompt 决定说什么,让解码参数决定怎么说。
核心
很多人在 prompt 里写"请你严谨一点"、"不要瞎说"——这些自然语言指令对模型行为的实际影响,远小于直接调整解码参数:把 temperature 从 1.0 调到 0.0,或把 top_p 从 1.0 调到 0.5。事实性任务用低温度,生成性任务用核采样(nucleus sampling),长文本生成靠重复惩罚(repetition_penalty)防退化。
Things to Remember
- 事实性任务:
temperature=0, top_p=1。 - 创造性任务:
temperature=0.7-1.0, top_p=0.9。 - 长生成防退化:
repetition_penalty=1.05–1.2, no_repeat_ngram_size=3-5。
延伸阅读
- The Curious Case of Neural Text Degeneration(arXiv:1904.09751)—— nucleus sampling(
top_p)的提出论文:证明 greedy / beam search 在长生成上必然退化为重复,提出按累计概率截断采样空间的解法。