Chapter 01

LLM/Prompt 基础:把模型当成一个会算账的组件

起点页把四大主题串成了一条因果链——这一章是链条的地基:把 LLM 当成一个会算账、会出错、会被注入的组件来理解,后面三章的每个方案都从这里的限制长出来。

本章你要建立的心智模型

  • 为什么 LLM 推理按 token 计费、注意力为何是 O(n²)、KV cache 在省什么
  • 采样参数怎么影响输出、生产里怎么配(含 OpenAI 不暴露 top_k 这类陷阱)
  • 幻觉的成因与可落地的缓解手段,以及为什么“让模型说不知道”很难
  • Function Calling 的真实机制:模型只产出调用意图、不执行——这是 Agent 的地基
洞察 · 这一章在面试里考什么

中高级面试很少直接问“什么是 temperature”。它问的是“你这个抽取任务 temperature 设多少、为什么”“窗口够大了为什么还要 RAG”“Function Calling 谁来执行函数”。这些题的底层都是同一个判断力:把 LLM 看成非确定、按 token 计费、会幻觉、不自己执行动作的组件,然后据此算账。下面六节就是这笔账的六个分项。

1.1自注意力与 KV cache(为什么 LLM 又慢又贵)

自注意力让每个 token 关注序列里所有 token,代价是计算与显存随长度二次增长。

为什么需要它

RNN 顺序处理序列、信息要逐步传递,长距离依赖会在传递中衰减,且无法并行训练。自注意力让任意两个 token 直接交互,一步建立全局依赖、可大规模并行——这是 Transformer 取代 RNN、把模型推到千亿参数规模的前提。代价记在了成本上:长度翻倍,注意力的计算量翻四倍。

一次注意力的机制是确定的四步:每个 token 由三组向量表示——Query、Key、Value(QKV)。用当前 token 的 Q 与序列中所有 token 的 K 做点积,得到相关性分数;除以 √d_k 缩放(防止点积过大把 softmax 推到梯度近零的饱和区);过 softmax 归一化成权重;再用这组权重对所有 V 加权求和,得到这个 token 融合了全局上下文的新表示。

关键在“所有 token”这三个字:序列里有 n 个 token,每个都要和另外 n 个算分,于是是 n × n 次交互——计算与显存都是 O(n²)。这就是上下文越长越贵、越慢的根因,也是后面 RAG 存在的第一个理由。

多头注意力(Multi-Head Attention)把 QKV 投影到多个子空间并行算,让不同的头学习不同的关系(一个头管句法、一个头管指代等),再拼接。它不改变 O(n²) 的量级,但显著增强表达力。

KV cache:把二次降成线性的工程手段

推理时 LLM 自回归地一个 token 一个 token 生成。生成第 t 个 token 时,注意力需要前面所有 token 的 K 和 V。朴素做法每生成一个就把整段历史的 K/V 重算一遍——累计下来是 O(n²) 的重复计算。KV cache 把已生成 token 的 K/V 缓存下来,每一步只为新 token 计算 K/V、复用缓存,于是每步的注意力计算从“二次”降到“对总长线性”。

陷阱 · 省了算力,显存成了新瓶颈

KV cache 不是免费的:缓存的大小随上下文长度线性增长,长上下文 + 高并发场景里,KV cache 占用的显存往往比模型权重还大,成为真正的部署瓶颈。这正是 MQA(多 Query 共享一组 K/V)、GQA(分组共享)这些变体被发明的原因——它们牺牲一点表达力,换 KV cache 显存的大幅下降。面试问“为什么要 GQA”,答案落点就是省 KV cache 显存。

无 KV cache 每步重算全部 K/V → 总量 ∝ n² 步 t1 t2 t3 t4 重算 4 格 有 KV cache 复用历史 K/V,每步只算新格 → 总量 ∝ n 虚线=缓存复用 实心=本步新算
图 1.3KV cache 把每步的重复计算消掉,但缓存本身随长度线性占显存。注意:上排实心格(每步重算量)越往后越多,是二次的来源;下排每步只新增一格,省的是算力,付出的是显存。

为什么主流是 Decoder-only

GPT、Claude 这类 decoder-only 模型用因果掩码(每个 token 只能看到自己左边)做自回归生成,天然契合 KV cache 复用——已生成的部分 K/V 永不改变,缓存一次用到底。T5 这类 encoder-decoder 的编码器是双向的(每个 token 看全序列),适合翻译、摘要这类 seq2seq 任务,但双向编码难以廉价复用 KV cache,且 scaling 与统一接口不如 decoder-only 简洁。这是 decoder-only 成为通用大模型主流的工程原因之一。

1.2采样参数:temperature / top-p / top-k / penalty

采样参数控制“从模型给出的概率分布里怎么挑下一个 token”,决定输出的确定性与多样性。

为什么需要它

模型每一步输出的是整个词表上的一个概率分布,不是单个答案。如果永远挑概率最高的(贪心),输出确定但呆板、易重复;如果完全随机,又会胡言乱语。采样参数就是在“确定/可复现”和“多样/有创造力”之间调的旋钮——生产里给抽取类任务和创意类任务配的值截然不同,配错了直接影响线上质量。

temperature:在 softmax 前对 logits 做缩放。T→0 退化为贪心(最确定、近似可复现);T=1 用原始分布(OpenAI 默认 1.0);T>1 把分布拉平、低概率 token 更易被选中(更随机)。事实问答、代码、结构化抽取设 0–0.3;头脑风暴、文案设 0.7–1.2。

top-p(核采样,nucleus sampling):按概率从高到低累加,取累积概率 ≥ p 的最小 token 集合再在其中采样。它是自适应的——分布陡峭时候选集小,分布平坦时候选集大。top-k:固定只保留概率最高的 k 个 token。两者都在“砍掉长尾垃圾 token”,但 top-p 随分布伸缩、top-k 是死数量。

陷阱 · OpenAI API 不暴露 top_k

OpenAI 的文本生成接口只给 temperature 和 top_p,没有 top_k;Anthropic、Gemini 则暴露 top_k。面试若张口“我用 top_k 控制 OpenAI 输出”会立刻露馅。另一条铁律:temperature 与 top_p 调一个就够,官方建议不要同时改两个——两个旋钮叠加会让分布的实际形状难以预测。

frequency_penalty(-2..2):随 token 已出现次数线性增大惩罚,越说越压、抑制重复。presence_penalty:只要 token 出现过就施加一次性惩罚,推动模型转向新话题。前者治“复读”,后者治“话题不发散”。

表 1.1 · 三类任务的采样配置(生产经验值)
任务类型temperaturetop_p / 其他取舍
结构化抽取 / 代码 / 事实问答0 – 0.3默认即可,慎用 penalty要可复现、要字段稳定,宁可呆板
对话 / 通用助手0.5 – 0.8top_p≈0.9兼顾稳定与自然,最常用区间
创意写作 / 头脑风暴0.9 – 1.2可配 presence_penalty 促发散要多样,接受偶发跑偏
想一想

一个从合同里抽取“甲方名称 / 金额 / 签署日期”并返回固定 JSON 字段的任务,temperature 设多少?为什么这里要慎用 frequency_penalty?

展开答案(先停 10 秒再点)

temperature 设 0(或 0–0.2):抽取要的是确定、可复现、字段对齐,随机性只会带来抖动。top_p 保持默认、不要再叠着调。

慎用 frequency_penalty 的原因:JSON 里字段名(如 "party_a"、"amount")本来就必须重复出现,frequency_penalty 会随出现次数惩罚这些 token,可能导致模型为了“少重复”而改写字段名、漏字段或破坏结构。结构化输出场景,penalty 通常关掉。

设计落点:随机性旋钮(temperature/top_p)调到最确定;重复惩罚旋钮(frequency/presence_penalty)在结构化任务里会与“格式必须重复”的需求冲突,应关闭。

1.3上下文窗口与 “Lost in the Middle”

上下文窗口是模型一次能处理的最大 token 数;即便窗口够大,中间的信息也容易被忽略。

为什么需要它

窗口决定了你一次能塞多少 prompt + 历史 + 检索内容。它是硬上限:超了就被截断。但比“塞不下”更隐蔽的问题是——塞得下不等于用得好。理解窗口的两层限制(容量上限 + 位置偏差),是判断“该全塞、还是上 RAG、还是先摘要压缩”的前提。

主流窗口在快速变大(截至 2026-06:GPT-5.5 约 256K–1M、Claude 4.x(Opus 4.8 / Sonnet 4.6)200K–1M、Gemini 3.x Pro 1M 起、最大档已到数 M 级)。型号与窗口每隔几个月就翻新,面试记框架、别背数字——因为窗口再大,三件事都没变:注意力的 O(n²) 成本让长上下文又贵又慢;模型的内部知识仍会过期、不可控;以及——位置偏差。

Lost in the Middle:研究发现,当关键信息放在长上下文的开头或结尾时,被正确利用的概率高(约 85–95%);放在中部时明显下探(约 76–82%)。召回率随位置呈 U 形。(具体数值为示意,趋势来自 Liu et al. 的 U 形结论,并非某一篇论文的实测值。)这意味着“把 50 个文档一股脑塞进 200K 窗口”并不能保证模型用到中间那几个关键段落。

被正确利用的概率 信息在上下文中的位置(开头 → 结尾) 90% 80% 75% ~92% ~82% ~77% 最低 ~82% ~90% 开头 前部 中部 后部 结尾
图 1.2召回率随位置呈 U 形:首尾高、中部塌陷。注意:把关键信息放在上下文首尾;长上下文 ≠ 信息都会被用到——这是 RAG 里要把最相关结果排到首尾、而非随意拼接的直接依据。(图中百分数为示意,刻画的是 Liu et al. 的 U 形趋势,不是某篇论文的实测点值。)

所以“窗口够大了为什么还要 RAG”有四个并立的答案:① O(n²) 让长上下文的延迟与费用线性甚至超线性上涨;② Lost in the Middle 让“塞进去”不等于“用得上”;③ 模型权重里的知识会过期、私有数据根本不在其中;④ 把整库塞进窗口既不可控也不可审计。RAG 是用检索把“最相关的一小撮”放进窗口,既省钱又规避位置偏差。

洞察 · 长上下文 vs RAG 不是二选一

面试问“有了 1M 窗口还要不要 RAG”,强答案不站队,而是按场景算账:单篇 50 页文档、要全局推理 → 倾向全塞长上下文;知识库有几万篇、要可更新可溯源 → RAG;超长且大部分无关 → 先摘要/压缩再喂。判断维度是相关密度、可更新性、可溯源性、成本,不是窗口大小本身。

1.4幻觉:成因与缓解

幻觉是模型生成了流畅但与输入或事实不符的内容——它在“编”,而且自己不知道在编。

为什么需要它

幻觉是 LLM 落地最大的信任障碍。理解它不是模型“偶尔犯错”,而是训练目标的结构性产物,才能选对缓解手段:知道根因在“优化流畅度”和“评测奖励蒙答案”,就明白为什么单纯调 prompt 压不住,需要 RAG 接地、需要允许弃权这类组合拳。

分两类:内在幻觉(intrinsic)——输出与给定输入自相矛盾(如总结时改写了原文事实);外在幻觉(extrinsic)——输出与客观事实不符,但输入里没有可对照的依据(如编造一条不存在的 API、一个假的引用)。

成因有三层。第一,训练目标:下一 token 预测优化的是“流畅、像人话”,不是“真实”——一句通顺的假话和一句通顺的真话,在语言建模损失上没有本质区别。第二,评测机制:OpenAI 2025 年的分析指出,主流评测在“蒙一个答案”和“老实说不知道”之间奖励前者——蒙对了得分、弃权得零分,于是模型被训得倾向于自信地猜而非承认无知。第三,数据:训练语料的覆盖缺口、歧义、以及模型校准(confidence 与正确率不匹配)问题。

表 1.2 · 幻觉缓解手段与各自的边界
手段怎么起作用边界 / 代价
RAG 接地把权威资料放进上下文,让模型“据此回答”而非凭记忆检索错/不全时照样幻觉;见下方追问
Prompt 约束明确“仅根据提供的上下文作答,无依据则说不知道”软约束,模型会违背
降低 temperature减少随机发挥只压“随机型”错误,压不住系统性错误
引用 / 溯源要求标出处,便于人工核验引用本身也会被编造
允许“不知道” + RLHF 校准训练/提示模型在低置信时弃权需改训练或评测激励,单靠 prompt 难根治
陷阱 · “让模型说不知道”比想象中难

直觉上加一句“不确定就说不知道”就能压幻觉,但模型被预训练和评测共同训成了“倾向自信作答”。Prompt 是软约束,扭不过训练时形成的强先验;真正有效的是从评测/训练激励层面奖励弃权,外加 RAG 把答案锚到可核验的上下文。这也是为什么幻觉是“缓解”而非“消除”。

想一想

你已经接了 RAG,把正确的资料检索进了上下文,模型却还是给出了和资料冲突的答案。问题出在哪?怎么治?

展开答案(先停 10 秒再点)

RAG 给对了上下文仍幻觉,常见原因:① 上下文里同时有相关和噪声段落,关键信息恰好落在中部被 Lost-in-the-Middle 忽略;② 模型的参数化先验压过了上下文(它“记得”一个更常见但过时的答案,于是无视检索内容);③ prompt 没强约束“仅据上下文、冲突时以上下文为准”。

缓解:把最相关片段排到上下文首尾(呼应 §1.3 的 U 形);prompt 显式声明“仅根据提供的资料作答,与你已知冲突时以资料为准,资料不足则说无法回答”;降低 temperature;加引用要求让答案可逐句溯源;必要时缩短上下文、提高相关密度。

设计落点:RAG 不是“检索对了就万事大吉”,检索质量、上下文排布、prompt 约束、参数先验四者协同,缺一仍会幻觉。

1.5结构化输出(JSON mode / 约束解码)

结构化输出让模型稳定吐出可被程序解析的格式(通常是符合 schema 的 JSON)。

为什么需要它

Agent 和后端把 LLM 当组件用,下游要拿字段做路由、入库、调接口。自由文本里夹一句“好的,这是结果:{…}”会直接让 json.loads 崩。没有结构化保证时,工程师要写正则抠 JSON、加重试、做容错——又脆又费。结构化输出把“格式正确”从碰运气变成可保证。

从弱到强四个层次:① few-shot 示例——给几个输入输出样例诱导格式,最弱、靠概率;② JSON mode——约束模型输出合法 JSON,但不保证符合你的具体 schema;③ strict schema(如 OpenAI strict: true 的 Structured Outputs)——保证字段、类型、必填都符合给定 JSON Schema;④ 约束解码(constrained decoding)——底层在每一步采样时就屏蔽掉会破坏 schema 的 token,从 token 级强制合法。

洞察 · 约束解码是 token 级强制,不是事后校验

这是高频考点也是高频误解。约束解码的强保证不靠生成完再校验+重试,而是在解码的每一步用 schema 编译出的状态机限制可选 token 集——非法 token 的概率直接被置零,模型只能在合法分支里采样。所以它的“合法”是构造性保证,不是概率性祈祷。事后 try/except + 重试是另一条更弱的兜底路线。

structured_output.py Python
# 演示用:OpenAI Structured Outputs(strict schema,非事后校验)
from openai import OpenAI
client = OpenAI()

schema = {
    "type": "object",
    "properties": {
        "party_a": {"type": "string"},
        "amount":  {"type": "number"},
        "sign_date": {"type": "string"},
    },
    "required": ["party_a", "amount", "sign_date"],
    "additionalProperties": False,   # 不允许多吐字段
}

resp = client.chat.completions.create(
    model="gpt-5.5",
    temperature=0,                   # 抽取任务 → 最确定
    messages=[{"role": "user", "content": contract_text}],
    response_format={
        "type": "json_schema",
        "json_schema": {"name": "contract", "schema": schema, "strict": True},
    },
)
# strict=True 下 schema 由约束解码保证;仍建议对业务语义做一层校验
表 1.3 · 让 LLM 稳定产出 JSON 的几条路线
手段保证强度什么时候用
few-shot 示例弱(靠概率)模型/接口不支持更强手段时的兜底
JSON mode中(合法 JSON,不保证 schema)只需“是 JSON”、字段自己再校验
strict schema / 约束解码强(token 级保证 schema)字段、类型、必填都要硬保证(首选)
事后校验 + 重试弱-中(概率性)无原生支持时的工程兜底,配合上面用
陷阱 · 字段缺失或多吐解释

常见失败:模型在 JSON 前后加“好的,以下是结果:”这类解释(破坏解析)、漏掉必填字段、或多吐 schema 外字段。治法:用 strict schema + additionalProperties: false 把多余字段堵死、用 required 强制必填;接口不支持 strict 时,约束解码方案(如 outlines、JSON-mode + 重试)兜底;并始终对解析结果做一次业务语义校验(schema 合法 ≠ 业务正确)。

1.6Function Calling:工具调用的地基

Function Calling 让模型产出“要调用哪个函数、传什么参数”的结构化意图——但模型从不执行。

为什么需要它

LLM 本身只会生成文本,不能查数据库、调 API、读文件。Function Calling 是给它装“手”的标准机制:你把可用工具的 JSON schema 告诉模型,模型在需要时输出一个结构化的调用请求,由你的 runtime 真正执行、再把结果喂回。把这个机制循环起来,就是 Agent 的最小内核——所以它是第 3 章 Agent 架构的地基。

真实机制是四步循环,关键在于职责分离:模型负责“决定调什么、传什么参数”,你的 runtime 负责“真正执行 + 把结果回填”。模型自己从不触碰数据库或网络。

用户提问 user message 模型(LLM) 产出 tool_call 或最终答案 runtime 执行函数 查 DB / 调 API / 读文件 结果回填 作为 tool message 最终答案 → 用户 ① tool_call(name+args JSON) ② 执行 ③ 回填→模型再决策 ④ 不再需要工具
图 1.1Function Calling 的四步循环:模型与 runtime 职责分离。注意:模型从不执行函数——它只产出“要调什么”的结构化意图;执行和喂回都是你的 runtime 干的。这就是 Agent 循环的最小单元。
function_calling_loop.py Python
# 演示用:四步循环的骨架(OpenAI 风格)
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "查询某城市当前天气",  # 描述写清楚,模型靠它判断该不该调
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

messages = [{"role": "user", "content": "北京现在天气怎么样?"}]

while True:
    resp = client.chat.completions.create(
        model="gpt-4o", messages=messages, tools=tools,
    )
    msg = resp.choices[0].message
    if not msg.tool_calls:           # 模型不再要工具 → 这是最终答案
        print(msg.content)
        break
    messages.append(msg)             # 记下模型的调用意图
    for call in msg.tool_calls:      # 可能并行多个 tool_call
        args = json.loads(call.function.arguments)
        result = dispatch(call.function.name, args)   # 你的 runtime 真正执行
        messages.append({            # 结果作为 tool message 回填
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps(result),
        })
    # 回到循环顶:把结果喂回,模型据此决定继续调工具还是给最终答案

这段循环就是 Agent 的雏形:单轮是“一次工具调用”,多轮叠加 + 让模型自己决定下一步,就成了 ReAct 式的“推理-行动-观察”循环。第 3 章会在它上面加规划、反思、记忆。

提示 · tool 的 description 和 schema 是选对工具的关键

模型靠 description 和参数 schema 判断“该不该调、调哪个、传什么”。描述含糊(“处理数据”)会让模型选错或漏调;参数 schema 写紧(类型、枚举、必填、说明)能显著提高调用正确率。工具选错往往不是模型笨,而是工具描述没写清楚。

想一想

模型一次返回了两个 tool_call(比如同时要查天气和查汇率),该怎么处理?顺序执行还是并行?

展开答案(先停 10 秒再点)

现代接口支持并行 tool_call:一条 assistant 消息里带多个 tool_calls。处理方式——遍历每个调用、分别执行(彼此无依赖时可并发执行以省延迟),把每个结果都作为独立的 tool 消息回填,且每条要带对应的 tool_call_id 让模型对得上。全部回填后再进入下一轮,模型据此给最终答案或继续调用。

陷阱:① 漏回填某个 tool_call_id 会让接口报错或模型困惑;② 若两个调用有依赖(B 要用 A 的结果),模型通常会分两轮发起,而不是一轮并行。

1.7微调:LoRA / SFT / DPO 与什么时候用它

微调是用领域数据继续训练模型、改变模型本身的行为与风格;它改的是“能力/语气”,不是“实时知识”。

为什么需要它

prompt 调不动的稳定格式、领域语气、特定能力,要靠微调把它固化进权重;但“实时/私域知识”是 RAG 的活,微调改不动——知识一变就得重训,固化进权重的旧知识反而成了包袱。

按“更新多少权重”分三档。全参微调更新模型的全部权重,效果上限最高,但要存一整份梯度与优化器状态,显存与成本最高,几十亿参数往上单卡就吃不下。PEFT / LoRA冻结主干权重不动,只在权重旁注入一对低秩矩阵 A·B(秩 r 远小于原维度)并只训练它们,可训练参数量降到全参的零点几个百分点,显存大幅下降,且训练产物只是一个小适配器——同一主干可热插拔多个 LoRA,按任务切换。低秩为什么够用:微调要打的“补丁” ΔW 经验上是低内在秩的——适配一个新任务真正需要改变的方向,远少于权重矩阵的维度,所以用一对秩 r 的小矩阵 A·B 就能近似覆盖绝大部分 ΔW,而不必动整块权重。这正是 LoRA 不掉太多效果的根因,也解释了 r 的取舍:r 太小连这点低秩结构都装不下、欠拟合;r 取 8–16 多数任务就够;再大只是趋近全参、徒增开销与过拟合风险。QLoRA在 LoRA 之上把冻结的主干量化到 4-bit 再训练适配器,进一步压低显存,让单卡微调较大模型变得可行。

按“训练目标”分两层。第一层 SFT(监督微调):喂“输入 → 理想输出”的成对数据,让模型模仿示范答案,把格式与能力学进去。第二层偏好对齐,目标是让模型懂“同一个问题,哪个回答更好”:RLHF走 PPO 强化学习、需要先训一个独立的奖励模型再用它打分调策略,链路长、调参敏感;DPO(直接偏好优化)直接拿“更优/更差”的偏好对当训练信号、省掉独立奖励模型,更简单也更稳定,近年常用。常见配方是先 SFT 打底、再用 DPO 做偏好对齐。

表 1.4 · 全参微调 / LoRA / QLoRA 怎么选
方案显存开销训练成本效果上限典型场景
全参微调最高(存全量梯度+优化器状态)最高最高数据充足、要榨干效果、算力不缺
LoRA低(只训低秩适配器)低接近全参,多数任务够用大多数领域适配,最常用默认
QLoRA最低(主干 4-bit 量化)低略低于 LoRA(量化损失)单卡微调大模型、资源受限
代价

微调不是写句 prompt 那么轻:要准备标注数据、搭训练 pipeline、做评估,且知识类需求一旦更新就要重训一遍。所以“知识会变”的需求用 RAG 而非微调——微调固化的是能力与语气,让会变的知识走检索,让稳定的行为走权重。

何时 RAG、何时微调、何时 prompt——三者不是互斥而是分工,对比见 02 章 §2.1。

1.8推理模型与 test-time compute

推理模型在给出答案前,先自己生成一长串“思考”token,用推理时的额外算力换准确率——这是 2025–2026 最大的范式变化。

为什么需要它

§1.2 末尾的 CoT 是 prompt 层的技巧——你求模型“一步步想”,它配合与否全凭概率。推理模型把“想”用强化学习训进了权重:模型学会在出答案前先展开一段长推理、自我验证、回溯纠错。这把“会不会推理”从 prompt 技巧变成模型能力,也带来一套全新的成本与延迟账,是 2026 中高级面试的必问点。

代表模型(截至 2026-06):OpenAI o3 / o3-pro、Claude 扩展思考(extended thinking)、Gemini Deep Think、开源的 DeepSeek R1(用 RL 直接训出推理能力、权重与论文公开)。它们共同的机制是 test-time scaling:给模型越多“思考预算”(推理 token),难题准确率越高——把原来只在训练时堆的算力,搬到了推理时。

但这条曲线不是单调上升。研究发现“想太多”反而掉分(overthinking):超过某个点后,模型会推翻本来正确的答案、在简单题上空耗。所以思考不是越多越好,存在一个任务相关的最优思考量。

任务准确率 思考预算(推理 token) 想太少:欠推理 最优思考量 过度思考 → 掉分
图 1.3test-time compute 不是越多越好:准确率随思考预算先快升,到“最优思考量”后走平,再加就 overthinking 掉头向下。注意:别把“给推理模型多想一会儿”当免费午餐——思考 token 照常计费、拉高延迟,过了最优点反而更差。

能力的代价很直接:思考 token 单独计费、照常烧钱,o 系列单价约为“快”模型(Haiku 档)的 10×,延迟也从亚秒级涨到数秒甚至更久。

表 1.5 · 普通模型 vs 推理模型——怎么选
维度普通模型(GPT-5.5 / Sonnet 档)推理模型(o3 / 扩展思考 / R1)
擅长抽取、改写、对话、格式化、高频低延迟数学、规划、多步推导、复杂代码、要自我验证的题
延迟亚秒级首 token先思考数秒到数十秒再出答案
成本基准思考 token 另计,约 10×
选择判据“想一下就会”的任务 → 普通模型“想不深就答错”的任务 → 推理模型;其余别为推理付费
陷阱 · 别给推理模型堆 few-shot CoT

推理模型自带内化的推理过程,再在 prompt 里堆“一步步想”式的 few-shot CoT 示例,反而会干扰它、白烧 token——官方建议对推理模型用简洁直接的指令,把“怎么想”交给模型。另一个高频陷阱是无脑调大思考预算:过了最优点就是 overthinking,更慢、更贵、还更差。

洞察 · 推理 vs 脚手架

推理模型把一部分“多步思考”收进了模型内部,这和 03 章 §3.3 的 ReAct / Plan 这类外部推理脚手架是一笔取舍:纯“想”的难题,让模型在内部思考往往比搭一圈循环更省事;但要接地到外部世界(查库、调 API),推理模型替代不了工具循环。

想一想

一个要“查实时库存再回复”的客服任务,把模型换成更强的推理模型,能解决问题吗?

展开答案(先停 10 秒再点)

不能。推理模型强在“想得更深”,解决不了“够不到外部数据”——实时库存在数据库里,模型再会推理也变不出来。这类任务的瓶颈是接地,要的是 Function Calling / 工具循环(§1.6、§3.3)把库存查回来,而不是更长的思考。把推理模型用在它不解决的瓶颈上,只会更慢更贵。反过来,“证明这道数学题”“规划一套多步迁移方案”这种纯推理难题,才是它的主场。

§面试题检索

先合上教程,把每题的答案在心里过一遍或写下来,再点开对照。直接看答案等于把这一节当再读一遍。每题标了是否高频,答案给的是“强候选会答到的点 + 面试官的追问”。

1. [高频] Transformer 的自注意力如何工作?为什么比 RNN 更适合长序列?

参考答案 + 追问

答:每个 token 生成 Q/K/V 三组向量;用 Q 与所有 token 的 K 做点积得相关性分数,除以 √d_k 缩放,过 softmax 归一化成权重,再对所有 V 加权求和,得到融合全局上下文的新表示。相比 RNN:① 任意两 token 直接交互,长距离依赖不随距离衰减(无梯度消失);② 全序列并行计算,训练高效;③ 全局依赖一步建立。代价是计算与显存 O(n²)。

追问:多头的意义?MHA / MQA / GQA 区别与为何要 GQA?多头让不同子空间并行学不同关系(句法、指代等),增强表达力。MHA:每个 Query 头配独立 K/V 头。MQA:所有 Query 头共享一组 K/V,大幅减小 KV cache 但表达力下降。GQA:把头分组、组内共享 K/V,是 MHA 与 MQA 的折中。要 GQA 的核心动机是省 KV cache 显存,在长上下文/高并发下让显存可控,同时尽量不掉质量。

追问:位置信息从哪来?自注意力本身对顺序不敏感(打乱 token 结果相近),位置信息靠位置编码补:早期是绝对/正弦位置编码,当前主流是 RoPE(旋转位置编码)——把位置以旋转的形式注入 Q/K,天然编码相对位置、且对外推到更长上下文更友好,是现在大模型的常见选择。

2. [高频] temperature、top-p、top-k 分别如何影响输出?生产里怎么配?

参考答案 + 追问

答:temperature 在 softmax 前缩放 logits 调随机性(0=贪心确定,>1 更随机);top-p(核采样)取累积概率 ≥ p 的最小 token 集合、自适应;top-k 取固定前 k 个。生产:事实/抽取/代码类 temperature→0;创意类调到 0.9–1.2;temperature 与 top_p 二选一调,不要同时改。

追问:JSON 结构化输出为什么慎用 repetition/frequency_penalty?OpenAI 有 top_k 吗?frequency_penalty 随出现次数惩罚 token,而 JSON 的字段名必须重复出现,惩罚会导致模型改写字段名、漏字段或破坏结构,所以结构化场景通常关掉。另外 OpenAI API 不暴露 top_k(只有 temperature、top_p),Anthropic / Gemini 才有 top_k。

3. [高频] 什么是上下文窗口?窗口够大了为什么还要 RAG?

参考答案 + 追问

答:上下文窗口是模型一次能处理的最大 token 数(截至 2026-06,主流旗舰普遍 200K–1M+,Gemini 系列最大档到数 M 级;型号窗口每几个月翻新,记框架别背数字)。窗口再大仍要 RAG,原因并立:① 注意力 O(n²),长上下文延迟和费用高;② Lost-in-the-Middle,中部信息召回低;③ 模型内部知识会过期、私有数据不在其中;④ 整库塞窗口不可控、不可溯源。RAG 用检索把最相关的一小撮放进窗口,省钱且规避位置偏差。

追问:长文档该全塞、RAG 还是摘要压缩?按相关密度和需求定:单篇要全局推理→倾向全塞长上下文;几万篇要可更新可溯源→RAG;超长但大部分无关→先摘要/压缩再喂。维度是相关密度、可更新性、可溯源性、成本,不是窗口大小。

4. [高频] 大模型幻觉分哪几类?怎么缓解?

参考答案 + 追问

答:两类:内在幻觉(与给定输入冲突,如改写原文)vs 外在幻觉(与客观事实冲突,如编造引用/API)。缓解:RAG 接地、prompt 约束“仅据上下文”、降 temperature、引用溯源、RLHF、允许模型说“不知道”。根因之一是训练/评测奖励“蒙答案”而非“弃权”(OpenAI 2025),所以单靠 prompt 压不住。

追问:RAG 给对了上下文还幻觉怎么办?可能是关键信息落在中部被忽略、参数化先验压过上下文、或 prompt 没强约束。治法:相关片段排到上下文首尾、prompt 显式“冲突时以资料为准、不足则说无法回答”、降 temperature、加引用要求逐句溯源、提高相关密度。

5. Function Calling 是什么?底层怎么实现?LLM 自己执行函数吗?

参考答案 + 追问

答:你把工具的 JSON schema 传给模型,模型在需要时输出结构化的调用请求(函数名 + 参数 JSON)。模型不执行函数——由你的应用/runtime 真正执行,把结果作为 tool message 回填,模型再据此生成最终答案或继续调用。四步循环:用户提问 → 模型产出 tool_call → runtime 执行 → 结果回填 →(循环)模型给最终答案。多轮叠加就是 Agent 雏形。

追问:并行多个 tool_call 怎么处理?description/schema 怎么写让模型选对?并行:一条消息可带多个 tool_call,逐个执行(无依赖可并发)、每个结果独立回填并带对应 tool_call_id。写法:description 要具体(不要“处理数据”这种),参数 schema 收紧类型/枚举/必填/说明——选错工具常是描述没写清楚,不是模型笨。

6. CoT / 自洽性(self-consistency) / ToT 有什么区别?

参考答案 + 追问

答:CoT(思维链)让模型“一步步想”,把推理显式写出来,线性单条。self-consistency(自洽性)对同一问题采样多条 CoT,对最终答案做多数投票(在 GSM8K 上较单条 CoT 提升约 +17.9%)。ToT(Tree of Thoughts)把推理组织成树,可探索多个分支并回溯,适合需要搜索的问题。准确率依次增强,但 token 消耗和延迟也依次上涨。

追问:什么场景值得上 ToT?解空间大、需要试错与回溯、单条思维链容易走进死胡同的任务(如规划、数学搜索、谜题)。代价是 token 和延迟成倍增加,简单问答不值得——能用 CoT 解决就别上 ToT。

7. 怎么让 LLM 稳定产出 JSON?

参考答案 + 追问

答:从弱到强:few-shot 示例 → JSON mode(保证合法 JSON)→ strict schema(保证符合给定 JSON Schema)→ 约束解码(token 级强制,每步屏蔽会破坏 schema 的 token)。配合 few-shot 提示、失败重试 + 解析校验。关键认知:约束解码是 token 级构造性保证,不是生成完再校验;事后 try/except + 重试是更弱的兜底。

追问:字段缺失或多吐解释怎么治?用 strict schema + additionalProperties:false 堵多余字段、required 强制必填;接口不支持 strict 时用约束解码库(如 outlines)或 JSON-mode + 重试兜底;并始终对结果做业务语义校验——schema 合法不等于业务正确。

8. Decoder-only 为什么成了主流(vs encoder-decoder)?

参考答案 + 追问

答:decoder-only(GPT/Claude)用因果掩码自回归生成,已生成部分的 K/V 永不改变,能高效复用 KV cache;架构统一、scaling 简单,一个“续写”接口覆盖几乎所有任务。encoder-decoder(T5)的双向编码器适合翻译/摘要这类 seq2seq,但双向注意力难以廉价复用 KV cache,且接口与扩展不如 decoder-only 简洁。综合推理效率与通用性,decoder-only 成了通用大模型的主流。

9. [高频] 讲讲 LoRA 的原理:它为什么能用极小的代价接近全参微调的效果?

参考答案 + 追问

答:LoRA 冻结主干权重,只在权重旁注入一对低秩矩阵 A·B(秩 r 远小于原维度)并只训练它们,显存小、训练产物是个小适配器、可多套热插拔。它够用的根因是:微调要打的“补丁” ΔW 经验上是低内在秩的——适配新任务真正要改的方向远少于权重维度,所以秩 r 的 A·B 就能近似覆盖绝大部分 ΔW。

追问:秩 r 怎么选?r 是容量与开销的权衡:太小连低秩结构都装不下、欠拟合;r 取 8–16 多数任务够用;再大趋近全参且易过拟合,常配合 alpha 缩放调。

10. [高频] LoRA / QLoRA / 全参微调怎么选?

参考答案 + 追问

答:按显存与效果上限排:全参微调更新全部权重、上限最高但要存全量梯度 + 优化器状态、最贵;LoRA只训低秩适配器,显存低、接近全参、是多数任务的默认;QLoRA再把冻结主干 4-bit 量化,单卡也能微调较大模型,代价是量化带来的小幅精度损失。

追问:为什么知识更新类需求不该微调而该用 RAG?知识固化进权重后一变就要重训,成本高且旧知识难擦除;RAG 改的是外部检索库、即改即生效、还可溯源。微调管能力与语气,会变的知识交给 RAG。

11. 什么时候用 SFT,什么时候用 DPO / RLHF?

参考答案 + 追问

答:SFT(监督微调)喂“输入→理想输出”成对数据,让模型模仿示范、把格式与能力学进去,是打底。偏好对齐解决“同一问题哪个回答更好”:DPO直接用“更优 / 更差”偏好对训练、无需独立奖励模型,简单稳定;RLHF走 PPO + 独立奖励模型,更重、调参更敏感。常见配方是先 SFT 打底、再用 DPO 对齐。

12. [高频] 什么是推理模型 / test-time compute?什么时候该用、什么时候不该用?

参考答案 + 追问

答:推理模型(o3 / Claude 扩展思考 / R1)在出答案前先生成一段“思考”token,用推理时的额外算力换准确率(test-time scaling),推理能力是用 RL 训进权重的,不是 prompt 技巧。该用:数学、规划、多步推导、复杂代码等“想不深就答错”的题。不该用:抽取 / 改写 / 高频低延迟的简单任务——思考 token 另计(约 10×)、延迟高,纯属浪费。

追问:思考是不是越多越好?不是。超过任务的最优思考量会 overthinking——推翻正确答案、简单题空耗,准确率掉头向下。追问:推理模型能取代 Agent 吗?不能。它解决“想得深”,不解决“够到外部数据 / 执行动作”;要接地仍需工具循环(§3.3)。

进阶挑战 · 刚好够不着

同时要“严格 JSON”和“一定多样性”的抽取任务,参数怎么配?

给定一个抽取任务:既要求输出严格符合 JSON schema(字段、类型、必填都不能错),又希望对某个自由文本字段(比如“摘要”或“标签建议”)有一定多样性、不要每次都一模一样。你会怎么同时控制 temperature、采样和结构化手段?说出你的参数组合与理由。

提示(卡住再展开)

“格式严格”和“内容多样”是两个正交的旋钮,分开控制:格式靠结构化手段(strict schema / 约束解码在 token 级保证 schema,与 temperature 无关——约束解码是在采样分布上做屏蔽,不影响合法分支内的随机性);多样性靠采样(适度调高 temperature 或用 top_p)。所以可以“约束解码保证 schema + temperature 取中等值(如 0.5–0.7)”:结构永远合法,自由字段又有变化。还要注意:关掉会伤结构的 frequency_penalty;对必须确定的字段(如金额、日期)与需要多样的字段(如摘要)若想分别控制,可拆成两次调用或在 prompt 里分区约束。