专业书籍精读 · Generative AI System Design Interview · 第 4 章
Generative AI System Design Interview · Ch 4 · Ali Aminian, Hao Sheng & Alex Xu · 2024
你在聊天框里打一句话,它回你一段像样的话,像个助理。这一章讲的是:一台「读遍了全世界文字」的机器,怎么被调教成这个助理——而这几步,和「让它更博学」几乎没关系。
刚造好的那台机器其实什么都懂,但它不回答你。你问「怎么煮溏心蛋」,它很可能顺着往下写:「怎么煮溏心蛋?怎么煎荷包蛋?怎么……」——因为它从头到尾学的是接话:看见半句,猜下半句。而网上一个问题后面跟着的,本来就常常是另一个问题。它不是不会答,是没人告诉过它「被问了就该答」。
那就写规则教它?可「答得好」这件事根本写不成规则:该不该先给结论、该多长、要不要反问、什么时候必须拒绝——换个问题答案就变。它属于那种你一看就知道好不好、却说不出标准的事。
第一步,请人示范。 找人把一批问题亲手写出好回答,让机器照着模仿,像新人入职先读前辈写的范例。缺点很实在:范例写起来又慢又贵,写上几万条就到头了,覆盖不了人们会问的一切。
第二步,请人当裁判。 同一个问题让机器写好几版,人只挑哪版更好——挑比写快十倍,而且两个人对「谁更好」的意见,比对「该打几分」的意见一致得多。把这些选择喂给另一台机器,训出一个打分员:递给它一个回答,它吐一个分。
第三步,对着打分员练。 机器自己写、打分员评分、往高分的方向挪一点点,反复。人不必再逐条参与了——人的判断已经装进那个打分员里。
关键还有一根绳子:不许离原来的自己太远。没有这根绳子,它会学会讨好打分员而不是把事做好——比如发现「写长一点分就高」,从此句句注水。
它每次只能看见眼前这一小叠纸,对话一长就装不下,所以要么把前面的话缩成摘要,要么把你以前说过的重要的事记进一个本子、用到时再翻出来。它也不会算大数、不知道今天的新闻——于是还要教它一件事:遇到自己不行的,就开口要工具,系统替它去查去算,把结果递回它手上,它再接着说。
代价得说清楚一句:同一套调教让它变听话,也让它变得爱顺着你——该说「你这个前提不对」的时候说了「你说得对」。讨好是这根绳子的影子,甩不掉,只能管。
读过的书决定它知道什么,后面这几步决定它愿意怎么跟你说话;而「说得好」没有标准答案,只能靠人一次次在两版之间挑一个,把标准慢慢喂进去。
想进到具体机制、记号和示意图? → 切到精读版
你以为 ChatGPT 的难点是把模型做得更聪明,其实知识在预训练那一步就基本定死了;这一章真正在解的是目标错配——预训练教的是「预测下一个 token」,产品要的是「听懂指令、按人的偏好作答、该拒绝时拒绝」。解法是三段式(预训练 → 监督微调 → 偏好对齐),而它的核心工程直觉只有一句:当「好」写不成损失函数时,就把人的两两比较训成一个可优化的打分器。
Part II 十道真题的第三道。上承 Ch3 翻译——那里至少还有参考译文可比,这里连参考答案都没有,评估方式必须整套换掉;下启 Ch5 图像描述,把生成从纯文本推到跨模态。现实对应 ChatGPT、Claude、Gemini 这类通用助理,以及任何「多轮对话 + 工具 + 安全边界」的产品后端。
预训练的目标只有一个:给定前文,预测下一个 token——它学的是互联网上的文本接下来长什么样,而网上一个问题后面常常跟着另一个问题、一段广告、一个目录。于是基座模型的典型失败不是「不会」,而是答非所问、继续出题。
第二层麻烦是「好」定义不出来。翻译至少有参考译文,代码至少能跑测试;而「帮我写封辞职信」的好回答有无穷多个,好坏取决于长度、语气、要不要反问、有没有越界——既写不成规则,也标不出唯一答案。
第三层是安全第一次成为系统需求:足够流利的模型会把有害内容说得同样流利,失败形态是「错得流畅」,不是报错。
不解决会怎样?会得到一个知识渊博却不可用的模型:格式不稳、听不听指令全看运气、随时可能被一句话诱导出不该说的话。这一章的全部工作,就是把「会说话」变成「会办事且守规矩」。
预训练买知识与语言能力:无标注文本、万亿 token 量级,算力是三段里的绝对大头。监督微调(SFT)买格式与意图:人工写的「指令 + 理想回答」示范把输出分布拽到「应答」这一侧,便宜见效快,天花板也明摆着——示范要人一条条写,而且它只能说「这样是对的」,说不了「那样更差」。
偏好对齐买排序:人不写答案,只在模型自己产出的几版里挑好坏,数据生产率高一个量级,信号形态正好补上 SFT 的缺口。一句话概括:能写示范就写,写不动了就改成挑选。
做法:同一个提示采样多版回答(常见 4–9 个),人排序,再用这些序对训一个打分模型,目标直白——让被选中的回答比落选的得分高。
为什么是比较而不是打分?因为绝对分数在人与人之间不可比:同一个回答,严格的标注者给 3 分、宽松的给 5 分,噪声大到淹没信号;而「A 和 B 哪个好」的一致性明显更高。这是整章最值得带走的一条方法论:绝对标准不存在时,退一步只要相对判断。
代价也在这里:奖励模型只是人类偏好的一个有限拟合,它自己的偏见(偏长、偏格式漂亮、偏自信语气)会被下一步忠实放大。
强化学习这一步的循环是:策略模型生成 → 奖励模型打分 → 往高分方向小步更新。PPO 的「小步」很重要,但更要紧的是目标里那一项 KL 惩罚——量新模型的输出分布离冻结的 SFT 参考模型有多远,走远了就扣分。
没有它会怎样?模型会去攻击奖励模型而不是取悦人:发现长答案得分高就无限加长,发现套话得分高就句句套话;同时丢掉原有能力,这笔损失叫对齐税。所以 KL 系数是这一段最要紧的旋钮:调小了跑偏,调大了学不动。
成本感觉:微软 DeepSpeed-Chat 公开的端到端数字里,13B 模型在 8 张 A100 上跑完三段约 13.6 小时,其中 PPO 独占 10.8 小时。对齐的算力大头不在训奖励模型,在那个采样—打分—更新的闭环上——工程上它也最重:策略、参考、奖励、价值四个模型要同时待在显存里。
多轮对话最朴素的做法是每轮把全部历史重新拼进提示。它的问题不是「记不住」,是账算不过来:一轮 500 token,20 轮就是 1 万 token;注意力的计算量随长度平方增长(长度翻倍、这部分成本约翻四倍),KV cache 的显存随长度线性增长且每个并发会话各占一份——先撞墙的往往不是上下文上限,而是显存决定的并发数。
所以真实系统把「记忆」拆成几层:系统提示(固定,可复用缓存)、近期原文(最近 k 轮,保语气与指代)、压缩历史(更早的轮次滚动摘要),再加一层可选的长期记忆:用户的稳定偏好写进外部存储,需要时检索回来。
两个常被忽略的坑:摘要有损且不可逆,摘掉的细节以后问不回来;长上下文里靠中间位置的信息更容易被忽略,要紧的东西要放在最前或最后。
模型有三样天生不行:不知道训练截止之后的事、不擅长精确计算、看不见私有数据。解法统一——让它输出一段结构化调用请求,系统执行后把结果回填进上下文,模型再接着生成。
工程上盯三件事。延迟:每次工具往返 = 一次完整前向 + 工具 RTT,两三轮下来端到端就从几百毫秒涨到数秒,所以要卡住最大调用轮数、能并行的一起发。可靠性:模型会调错工具、编造参数,参数得按 schema 校验,失败要有重试与兜底话术。信任边界:工具返回的内容进了上下文就和用户指令混在一起——提示注入正是从这里进来的,外部内容必须标明来源,且绝不赋予它指令权限。
安全是三道防线叠起来的:训练期用安全偏好数据把拒绝行为训进模型,输入侧分类器拦明显违规的请求,输出侧再过一遍。流式输出让第三道防线变难——字已经吐到屏幕上,撤回代价很高,只能分块延迟校验或接受「先吐后撤」的体验损失。
评估也要整套换:困惑度与用户满意度几乎不相关。可用的组合是人工成对比较(两版盲测,按胜率或 Elo 排序)+ LLM-as-judge(用强模型批量做同样的成对判决,便宜可回归,但有位置偏差与长度偏好,要靠交换顺序等手段纠)+ 红队 + 在线指标(点赞率、重新生成率、人工接管率)。
还有一条产品级取舍绕不过:过度拒绝。安全阈值一调高,违规率下去了,正常请求被拒的比例上来——这是对齐里最典型的一条两端都疼的曲线。
表 1 · 三段训练:各买到什么
| ① 预训练 | ② 监督微调 SFT | ③ 偏好对齐 | |
|---|---|---|---|
| 数据形态 | 无标注文本 | 指令 + 人写的理想回答 | 同一问题多版回答的排序 |
| 数据量级 | 万亿 token | 千到万条示范 | 数万到数十万条比较 |
| 单条人力 | 零(爬来的) | 最贵:要人动笔写 | 便宜:只需二选一 |
| 买到什么 | 知识与语言能力 | 格式、意图、基本口径 | 偏好、语气、拒绝边界 |
| 只做到这里 | 会续写,不会应答 | 像范例,但学不到「哪个更好」 | — |
| 代价 | 算力大头,改一次极贵 | 天花板由示范质量封死 | 训练不稳、易 reward hacking、有对齐税 |
表 2 · 对齐路线:四种做法
| 只做 SFT | RLHF · PPO | DPO | RLAIF / 宪法式 | |
|---|---|---|---|---|
| 要不要奖励模型 | 不要 | 要,且要在线打分 | 不训独立的,直接在偏好对上优化 | 要,但偏好标注由模型按成文原则生成 |
| 工程复杂度 | 最低 | 最高:四个模型同时占显存 | 接近 SFT | 中等,主要成本在写原则与校验 |
| 标注成本 | 每条都要人写 | 人只需排序 | 同左,且可复用现成偏好集 | 人只写原则,标注可规模化 |
| 代价 / 风险 | 拒绝边界与风格不稳 | 跑偏、对齐税、复现难 | 离线数据,无法在线探索,分布一偏就纠不回来 | 模型自身偏见被写进标准;原则含糊 = 行为含糊 |
| 适合 | 垂直窄场景、预算有限 | 要把通用助理做到顶格 | 多数团队的默认起点 | 安全规则多、要可审计可解释 |
表 3 · 对话记忆:四种做法
| 全量拼接 | 滑动窗口 | 滚动摘要 | 向量检索长期记忆 | |
|---|---|---|---|---|
| 成本随轮数 | 线性涨 token、平方涨注意力 | 封顶 | 封顶,但每轮多一次摘要调用 | 封顶,多一次检索 RTT |
| 丢什么 | 不丢 | 窗口外全丢,指代直接断 | 细节有损且不可逆 | 没被检索到的等于不存在 |
| 适合 | 短会话、客服单轮多问 | 闲聊、上下文弱相关 | 长会话、需要连贯人设 | 跨会话记住用户偏好 |
| 真实做法 | 四选一是伪命题:系统提示 + 最近 k 轮原文 + 更早的滚动摘要 + 按需检索的长期记忆,四层叠着用。 | |||
这套骨架远不止聊天机器人:任何「好不好只能由人判断」的产品都长这样——文案生成、代码助手、客服质检、AI 评审。先用示范定格式,再用成对比较定偏好,用一个替身打分器把人的判断规模化,最后死盯替身被优化坏的那天。
面试里它最值钱的一句是:把「模型答得不好」翻译成「偏好信号出了什么问题」。说出「这个 badcase 不是知识缺失,是奖励模型偏好长答案,我要在偏好集里补一批『简短且正确 > 冗长且正确』的对照」,比背任何模型名字都有说服力。
1.4 小时(约 $45),OPT-13B 在 64 张上 9 小时(约 $290)。对齐本身不是天价,贵的是第三段那个闭环。microsoft/DeepSpeedExamples · DeepSpeed-Chat ↗SFTTrainer / RewardTrainer / DPOTrainer / GRPOTrainer 等一整排训练器。本章的三段式是骨架,第三段的具体算法在书出版前后就已经换过一轮。huggingface/trl README ↗① 这章解的是目标错配:预训练教「预测下一个 token」,产品要「听懂指令、按偏好作答、该拒就拒」。
② 基座模型的典型失败不是不会答,而是继续出题:它学的是接话,不是应答。
③ 三段各买不同的东西:预训练买知识,SFT 买格式与意图,偏好对齐买「哪版更好」。
④ 核心方法论:绝对标准不存在时,退一步只要相对判断——因为人对「A 还是 B」远比对「打几分」一致。
⑤ 奖励模型是人的替身:把说不清的好压成一个标量,代价是它的偏见会被下一步忠实放大。
⑥ KL 惩罚是拴住替身的绳子:调小了 reward hacking,调大了学不动;对齐税就在这根绳子的松紧里。
⑦ 算力账:预训练是绝对大头;对齐内部最贵的是 PPO 那个采样—打分—更新的闭环。
⑧ 记忆不是一种做法而是四层叠用:系统提示 + 最近 k 轮原文 + 滚动摘要 + 按需检索的长期记忆。
⑨ 工具调用补上知识截止、精确计算与私有数据,代价是把信任边界推进了上下文:提示注入从工具返回值进来。
⑩ 验收靠成对比较 + LLM 裁判 + 红队 + 在线指标;安全阈值与过度拒绝是同一条曲线的两端。