跳到主要内容

找回来之后怎么答 — 提示是请求,不是约束

这一章讲三件事: 检索到的原文用什么形状交给模型; 交进去之后,写在提示里的要求有多少会被照做;以及照做不了的那些,该用什么手段真正管住。 它在全书链条里的位置: 前七章都在讲「怎么把对的东西找出来」, 从这一章起讲「找出来之后怎么用」 —— 这是六站流水线的最后一站。

1. 顶层全景

检索回来的几段原文


┌────────────────────────────────────────────────┐
│ 拼成一段文字交给模型: │
│ 你是一个助手。 │
│ 请根据下面的资料回答问题。 │
│ 资料:<原文段落,原样贴进来> │
│ 问题:<用户的问题> │
│ 回答: │
└────────────────────────────────────────────────┘


模型顺着这段文字往下写

├─ 你在里面写的「请怎样怎样」——它可能照做,也可能不照做
└─ 而不照做的输出,看上去照样像个正经答案

图说:上面这个框里的东西,就是这一章的全部对象。 它是一段普通的文字,不是一份配置,也不是一份合同。

一句话链条: 原文原样塞进提示 → 这种做法有名字、也有边界 → 塞进去之后你只能「写要求」→ 而要求不等于约束 → 真要管住输出,得靠提示之外的手段。

2. 最朴素的那种做法有名字:stuff

书在这里给了一句干净的定义:把检索到的文档原样塞进提示, 文档短的时候管用,否则会撑爆模型的输入上限1

这种做法的名字就叫 stuff(英文原意是「塞」)。 你在把这些步骤包好的那套库里,会看到它是一个可选项 —— 所以这个名字要记住,你出门会在配置里撞见它。

它的边界在哪儿

第 03 章说过,模型一次能看的文字有个上限。塞进去的资料越多,离这个上限越近。

取回 3 段、每段 300 字符 → 900 字符 够用
取回 20 段、每段 800 字符 → 16000 字符 多半塞不下
取回 100 段 → 必然塞不下

图说:`stuff` 没有任何应对办法——它就是「全塞」。
塞不下的时候要换别的做法(先各段分别总结再合并、或者逐段追问逐段修正),
**而这本书只演示了 `stuff` 这一种。**

3. 主走查:两句话的资料,一个问题,一次逐字复述

这一节是本章的主走查。这一章每一个机制,在这条线上都占一步。

书有一个配方,把语料写死在代码里,只有两句话2:

句 A:Retrieval-Augmented Generation (RAG) is a technique that improves
AI responses by combining document retrieval with language generation.
(RAG 是把找资料和写文字结合起来、以改进 AI 回答的一种技术。)

句 B:It reduces hallucinations by grounding answers in retrieved documents
instead of relying only on the model's memory.
(它把答案落在找回来的资料上、而不只靠模型自己的记忆,从而减少胡编。)

图说:注意句 B 的第一个词是 **It**。这两句话在原文里是挨着的,
所以「It」指谁一目了然。**待会儿它们会被拆开。**

问题是:How does RAG reduce hallucinations?(RAG 怎么减少胡编?)

六步,每步的实际内容

这一步做了什么具体的字串
把两句话各自变成一串数2 条,各 384 个数(第 04 章那个模型)
按相似度取前 2 条B 在前、A 在后 —— 和原文顺序相反
把这两条原样拼成一段(stuff)It reduces hallucinations … memory Retrieval-Augmented Generation (RAG) is a technique … generation
在前面加上要求其中一行写着 Do not just repeat words — provide a clear explanation.(不要只是重复词句 —— 要给出清晰的解释)
交给模型用的是第 01 章说过的那个 2.5 亿参数的小模型
模型给出答案句 A + 句 B,一字不差,而且顺序又倒回了原文的样子

第 ⑥ 步书印出来的原文是3:

Answer: Retrieval-Augmented Generation (RAG) is a technique that improves
AI responses by combining document retrieval with language generation.
It reduces hallucinations by grounding answers in retrieved documents
instead of relying only on the model's memory.

图说:把这段和上面的句 A、句 B 对一遍——**一个字都没变。**
而第 ④ 步的提示里,明明白白写着「不要只是重复词句」。

这条走查同时说明了三件事

第一,答案其实是对的。 两句话都被检索到了,而句 B 正面回答了问题。 这一次没有出错。

第二,它不是「解释」,是复述。 提示要的是解释,拿到的是原文。 要求落空了,而输出看上去完全正常 —— 这是第 5 节的全部内容。

第三,顺序被换过了。 第 ② 步里 B 排在 A 前面,而 B 是以「It」开头的。 这是第 4 节的内容。

4. 检索回来的几段是按相似度排的,不是按原文顺序排的

现象

看第 ② 步:句 B 排在句 A 前面。

为什么?因为问题问的是「怎么减少胡编」,而句 B 正是讲这个的,分数更高。 排序的依据是「和问题有多像」,不是「在原文里谁在前」。

后果

交给模型的那段文字,实际长这样:

It reduces hallucinations by grounding answers in retrieved documents …
Retrieval-Augmented Generation (RAG) is a technique that …

图说:**代词跑到了它的指代对象前面。**
单看第一句,「It」指谁是无解的——那个词要到下一句才出现。

这一次没出事,因为两句都在,模型自己把顺序理回来了。 但这是运气,不是设计。 只要检索只取回句 B 一条,或者两句之间还夹着别的段落, 「It 指谁」就没有着落了。

这和第 03 章那颗雷是什么关系

第 03 章那颗雷叫块内指代断裂:一块文字里留下了失去指代对象的代词,这一块就永远检索不准。

这里不一样:两块都在,只是被摆错了顺序。 病的位置不同:

第 03 章那颗雷这一节说的
坏在哪切块的时候把指代对象切没了指代对象还在,只是排到了后面
什么时候发作检索时(那一块打不出高分)生成时(模型看不出 It 指谁)
怎么修在句子边界下刀、开大重叠交给模型之前,把选中的段落按原文顺序摆回去

「交给模型之前该怎么排」这件事,全书一个字没提。

5. 提示是请求,不是约束

这是这一章的落点,也是这本书最该被带走的一条。

先把话说死

写在提示里的每一句要求,对模型来说都只是「眼前这段文字的一部分」。 它会照着这整段文字往下写 —— 包括你写的要求,也包括你贴的资料。 没有任何机制强制它遵守其中的任何一句。

这不是这个模型的缺陷,是这类模型的工作方式 —— 第 01 章第一句话就说了: 它做的事是「照着眼前这段文字往下接」。

三次现场

这本书里,同一件事发生了三次,一次比一次干净:

提示里写了什么输出是什么在哪
「不要只是重复词句,要给出清晰的解释」两句原文一字不差第 3 节那条走查
「用 [1]、[2] 这样的方式注明出处」一个方括号都没有第 7 节
「严格按下面这个 JSON 格式回答」+ 一份模板一个短语,不是 JSON第 6 节

有一部分要算在模型头上

先分清两种模型。 第 04 章那个只负责把文字编成一串数,不会说话; 这一章这个负责写出答案,叫生成模型 —— 六站流水线里只有最后一站用它。

第 01 章说过,这本书的生成模型逐章缩水: 前六章用的是 30 亿参数那个,从这一章开始换成了 2.5 亿参数的那个, 而书从头到尾没有交代这件事。

小模型对复杂指令的服从度确实差得多。 换个大模型,上面三条里有些能改善。

但「能改善」不等于「有保证」。 这条界线要划清楚:

换更大的模型 → 照做的比例上升 ← 概率问题
改用受约束的接口 → 不合规的输出根本出不来 ← 机制问题

图说:这两件事不在一个层面上。**第 6 节讲的就是后一种。**

那提示还有用吗

有,而且这一章唯一真正靠提示起作用的那件事就在第 3 节: 把找回来的原文塞进提示,模型的答案就落在这些原文上。

这件事有个名字叫上下文接地 —— 「接地」是从电学借来的说法, 意思是给答案一个可以踩实的地方。

它之所以有效,恰恰是因为它不是在下命令,而是在改变模型眼前看到的东西。

判断(我们的,不是书里的): 提示里的内容可以分成两类, 它们的可靠程度差一个数量级 —— ① 提供材料(贴资料、给例子、划定范围):可靠,因为它改变的是模型看到的东西; ② 下达指令(不许怎样、必须怎样、按某种格式):不可靠,因为它只是文字。 这本书的九个提示配方里,只有第 ① 类那一个稳定生效。 如果错,会错在: 如果换上今天的大模型,第 ② 类指令的服从率能高到实用, 那么这条界线就只在小模型上成立。判据是拿同一批提示在大模型上重跑 —— 这本书全程本地小模型,没有这个对照组,我们也没有跑。

6. 另起一处:要它吐 JSON,而漂亮的那份是程序拼出来的

这是本章第一处另起的走查,因为它落在另一条线上:它是提示管不住的那一类。

先说需求

很多时候你要的不是一段话,是一份程序能直接读的数据。

一份数据里预先起好名字的那些格子,叫字段 —— 比如「问题」一个格、「答案」一个格、「用了哪几份资料」一个格:

{"question": "...", "answer": "...", "sources": ["..."]}

让模型照着事先定好的字段吐,而不是自由写一段话,这种输出叫结构化输出。 它的价值是下游程序不必再从一段话里抠东西。

书自己给了全书最有价值的一条忠告

书的原话说得很清楚:提示可以鼓励模型输出 JSON,但保证不了它真的解析得了; 少了几种专门的机制,模型会生成「看起来像 JSON、程序却读不出来」的文本; 生产环境要用受约束的输出接口,不能只靠提示4

书点名的机制里有一种叫函数调用:你把要填的格子事先声明给模型接口, 模型只能往格子里填,不能自由发挥。(另外两种是专门的 JSON 模式,和事后拿定义去校验一遍。)

这段话是对的,而且是全书最有工程价值的一句。

而书自己那个配方,恰好现场印证了它

那个配方在提示里画了一份模板,要求「严格按下面这个 JSON 格式回答」5。 代码随后做了两件事:

try: 把模型吐的东西当 JSON 解析
except: 解析失败 → **自己动手拼一个字典**:
query ← 代码里的那个问题
retrieved_context ← 代码里的那两条检索结果
answer ← 模型吐的原始文字,原封不动塞进来

图说:两条路都会印出漂亮的 JSON。**印出来的一样,来路完全不同。**

书印出来的那份 JSON 是这样的6:

"retrieved_context": [
"It reduces hallucinations by grounding answers in retrieved documents …",
"Retrieval-Augmented Generation (RAG) is a technique that improves …"
],
"answer": "grounding answers in retrieved documents"

两处证据说明它走的是 except 那一条路:

  1. retrieved_context 里那两条的顺序,和第 3 节那条走查一模一样(B 在前、A 在后)。 那是代码里的检索结果原样搬过来的,模型不可能凑巧照抄出这个顺序还带上方括号;
  2. answer 是一个残缺的短语(「把答案落在找回来的资料上」), 不是一个句子,更不是 JSON。它正是模型吐出来的那点东西被塞进字段里的样子。

所以:模型没有产出 JSON。JSON 是 Python 拼的。

今天该怎么做

补充(不在书里):真正管住格式的做法,是把格式交给模型接口,而不是写进提示。

写进提示: "请按这个格式回答:{...}" ← 模型可以不理
交给接口: 把字段定义作为一个参数传进去 ← 不合规的输出根本生成不出来
拿到结果再按同一份定义校验一遍 ← 不合规就报错,而不是悄悄放过

图说:这两件事今天在主流的库里是一个函数调用的事7而这本书连这个方向都没提 —— 它只在正文里说了「要用受约束的接口」,没有演示过一次。

7. 另起一处:要它标 [1][2],它一个方括号都没给

这是本章第二处另起的走查。

想干什么

你希望答案里带着出处:「这句话来自第 1 份资料」。 这样用户能自己去核。

书试了两次

第一次:把检索到的每段编上号拼进提示,写成 [1] (来源): 内容 的样子, 再在提示里要求「用 [1]、[2] 这样的方式注明出处」8

输出里的 answer 字段是这样的9:

"answer": "architecture that combines the ability of large language models (LLMs)
with a retrieval system to enhance the factual accuracy, contextual
relevance, and quality of generated response …"

图说:**一个方括号都没有。** 而且它连句子都不是——开头就缺主语。

第二次:另一个配方同样在提示里写了「引用来源的编号,像 [1]、[2] 那样」。 这一次输出里真的有 [1] 和 [2]。

因为那个答案是作者手打在代码里的一句话。 那段提示确实拼好了,而拼好之后从头到尾没有被用过一次 —— 程序直接把手打的那句话返回了10

判断(我们的,不是书里的): 这是全书最严重的一处演示失真。 前面几处是「代码没兑现正文的承诺」,读者照着跑至少能看到真实的失败; 这一处是「输出根本不是程序产生的」 —— 读者照着跑,得到的会是完全一样的那句话, 而且永远正确,因为它是常量。 如果错,会错在: 如果作者的本意是「先摆一个理想输出的样子,模型那部分留作练习」, 那这只是缺一句说明。但配方的安装清单里连生成模型都没装, 说明这段代码从来就没打算调用模型。

靠谱的做法

引用是工程问题,不是提示问题。

① 检索的时候,每一段都带着它的标签(第 02 章那一小袋标签)
② 拼提示的时候,给每一段编号
③ 模型答完之后,**由代码**把编号和标签对上,贴回答案下面

图说:第 ③ 步交给代码,答案里有没有方括号就不重要了。
**而书里那份 JSON 的 `sources` 字段,恰恰就是这么来的**——
它是从标签里取出来的,不是模型写的。这一半书做对了,只是没说破。

8. 九种提示法,真正靠提示起作用的只有一种

书用一整章讲怎么把提示写好 —— 琢磨提示该怎么写这件事本身有个名字,叫提示工程。

其中一种写法你在别处也常听到:让模型先把中间步骤一条条写出来、最后才给结论, 这种写法叫思维链。

中间步骤指的是这类句子:「资料里说了 X」「问题问的是 Y」「X 正好回答了 Y」—— 这种从已知一步步走到结论的过程叫推理。 把它写进输出,模型就不必一步跳到答案。

九个配方逐个看代码,情况是这样的:

配方书给它的名字代码实际做的事
82上下文接地真的靠提示:把检索到的原文塞进去 —— 第 3 节那条走查
83思维链模型没有写出任何推理;「Final Answer:」那一行是 Python 在找不到它时贴上去的,内容正好等于检索第 1 名11
84查询改写一次字符串替换:把 RAG 换成 Retrieval-Augmented Generation (RAG)。没有提示,也没有模型12
85多提示集成三个提示各答一遍,再让模型合成一份。最终答案退化成三者里最短的那个短语13
86置信度感知真的:拿检索的相似度算高 / 中 / 低(第 09 章讲)
87带引用作答答案是手打的字符串 —— 第 7 节
88结构化输出漂亮的 JSON 出自解析失败的兜底分支 —— 第 6 节
89摘要式提示把摘要长度写死,当场逼出一本不存在的书(第 09 章讲)
90证据高亮先过滤再摘要,三条证据里两条是改写出来的(第 09 章讲)

「思维链」那一处值得单独看一眼

书那个配方的提示里,确实写了 「一步一步想:先写 2–3 条推理要点,然后在 'Final Answer:' 后面写最终答案」。

书印出来的输出是11:

Model output:
Retrieval-Augmented Generation (RAG) is a technique that improves AI responses …

Final Answer: It reduces hallucinations by grounding answers in retrieved documents …

图说:第一行是模型吐的——**一句照抄的定义,没有任何推理要点。**
第二行的「Final Answer:」是代码在发现模型没写它时自己补的,
内容等于检索结果的第 1 名。**两行都不是推理。**

这一章讲的思维链,一次都没有真正发生。

第 7 章还有一处,同一个病,而且更值得看

上面那个配方不是孤例。 第 7 章也有一个配方挂着思维链的招牌,做法花哨得多: 让模型对同一个问题连答五遍,再从五个答案里挑一个交出去14

「挑一个」是这么挑的:

把「问题 + 检索到的资料」拼成一段参考文本,按第 04 章那套办法压成一串数
五个候选答案各自也压成一串数
谁离参考文本那串数最近,谁当选

书印出来的五个分数: 0.906 / 0.865 / 0.811 / 0.776 / 0.773
当选的是 0.906 那一个,程序把它当成答案打了出来。

问题在于这个「近」量的是什么。 参考文本里装着资料原文, 所以「贴着资料原文说话」这件事本身就能加分。 五个候选里最短、话说得最少的那条(0.773)垫底;当选的那条(0.906) 是把资料里那句定义最完整、最贴字面地复述了一遍的那条。 这条排序奖励的是复述,不是推理。

而五个候选里一条推理都没有。 五条都是把同一句定义换个说法再写一遍, 末尾统一缀一句「所以答案是 RAG」。提示里明写着「一步一步想」, 连答五遍,五遍都没想。

这个 0.906 还有第二重身份:它和答案一起被打进了输出,长得就像一个「我有多大把握」的数。 可它量的其实是「答案和资料有多像」—— 越抄越高。 它到底算不算一个「把握」,第 09 章第 4 节的那张表里有它一行。

还有一处:「上下文增强」里没有增强

书另有一个配方叫「上下文增强的回答生成」,正文说要把来源、作者、时间、 按领域打的标签、表格、要点这些线索嵌进回答里15

代码做的是:取回最相似的两句话,用空格拼起来,返回。 输出里那两句还是顺序反的、并且从句子中间断开的16

9. 作者的判断与证据

书里给了证据的:

说法证据
stuff 在文档短的时候管用,长了会撑爆输入上限书里那句定义;而它的配方全程只用两三句话的语料
提示可以鼓励 JSON,但保证不了它真的解析得了它自己那个配方的漂亮 JSON 出自兜底分支
上下文接地能让答案落在资料上那条走查的答案确实一字不差地来自资料

作者只是断言、没有给证据的:

说法缺什么
「思维链提示提高事实准确性与可解释性」输出里没有任何推理;那一行结论是代码贴的
「查询改写让模型生成不同措辞、同义词或子查询」代码里是一次字符串替换
「多提示集成靠排序、多数投票或置信度打分选出最好的」代码只是把三段话塞进第四个提示;结果选中了最短的那个
「上下文增强把来源、作者、时间戳嵌进回答」代码只是把两句话用空格拼起来
「生成前通常会用交叉编码器重新打分排序,这是高质量系统的标准做法」那个配方里没有交叉编码器;三段答案几乎一模一样17
「带引用作答」一次模型没标,一次答案是手打的

一句话:这一章的正文写的是一份提示工程的地图,而代码走的是另一条路。

10. 边界与局限

  • 只演示了 stuff 一种。 资料塞不下的时候该怎么办,全书没有第二种做法。
  • 上下文该怎么排序,一个字没提。 而排序会决定代词还找不找得到指代对象。
  • 没有一处演示受约束的结构化输出接口,尽管正文自己说了要用。
  • 没有一处把提示里的要求和实际输出对照过。 九个配方全部按「成功案例」收尾, 包括那些明显没做到的。
  • 这一章开头提了一句「安全生成需要一个独立的架构层,和检索、排序、事实核查分开」18, 然后全书再没出现过。 十个配方没有一个做这件事。
  • 另一个配方的说明里写着「好的系统必须在生成时用上对话历史」,而那个配方里没有任何对话历史。 多轮对话要到第 10 章才出现。
  • 这一章开始换了小模型而书不交代,所以它的每一处「输出很怪」都缺一个坐标。

11. 可带走的

全章那条走查,一行写完:

两句话的资料 → 问「RAG 怎么减少胡编」→ 按相似度取回 B 在前、A 在后 → 原样塞进提示(stuff)→ 提示里写着 「不要只是重复词句」 → 模型给出的答案是 句 A + 句 B,一字不差答案是对的,而要求落空了。

  1. 把资料原样塞进提示这种做法叫 stuff,短的时候够用,长了直接撑爆输入上限;
  2. 提示是请求,不是约束。 写在里面的要求,对模型来说只是「眼前文字的一部分」;
  3. 提示里的东西分两类,可靠程度差一个数量级: 提供材料(贴资料、给例子)可靠,下达指令(不许怎样、必须什么格式)不可靠;
  4. 唯一稳定生效的那一种叫上下文接地 —— 它有效,是因为它改的是模型看到的东西, 不是在下命令;
  5. 检索回来的段落是按相似度排的,不是按原文顺序排的; 交给模型之前把它们按原文顺序摆回去,代词才找得到指代对象;
  6. 要格式就别写在提示里,交给接口。 提示只能鼓励,接口才能保证 —— 这句话是书自己说的,也是全书最有价值的一条;
  7. 引用是工程问题,不是提示问题。 让代码把来源贴回去,别指望模型自己标;
  8. 看到「漂亮的 JSON」先问一句它是谁拼的 —— 书里那份是解析失败之后程序补的;
  9. 看到「思维链」先看输出里有没有推理 —— 书里那两行,一行是照抄,一行是代码贴的;
  10. 书里九种提示法,真正靠提示起作用的只有第一种。

12. 原文地图

主题原书章原文位置
stuff 的定义与边界CHAPTER 7 Response Generation with LLM in RAG Systemstext/14-fm-introduction.txt:77(搜「Stuff method works well when documents are short」) · text/14-fm-introduction.txt:159(搜「directly stuffs docs into prompt」)
「提示只能鼓励 JSON,保证不了合法」同上text/14-fm-introduction.txt:187(搜「it does not guarantee syntactically valid output」)
要求带引用,输出里没有方括号同上text/14-fm-introduction.txt:738(搜「cite them like [1], [2]」) · text/14-fm-introduction.txt:794(搜「architecture that combines the ability of large language models」)
「上下文增强」的承诺与实现同上text/14-fm-introduction.txt:1659(搜「metadata such as document source, author, timestamp」) · text/14-fm-introduction.txt:1733(搜「enriched_answer」) · text/14-fm-introduction.txt:1771(搜「A: RAG reduces」)
承诺了交叉编码器重排,配方里没有同上text/14-fm-introduction.txt:818(搜「a cross-encoder is often used to re-score and re-order candidates」) · text/14-fm-introduction.txt:991(搜「final_answer」)
「安全生成需要独立的一层」,此后再无下文同上text/14-fm-introduction.txt:9(搜「brand consistency」)
第 7 章那个思维链:连答五遍、按「像不像资料」挑一条同上text/14-fm-introduction.txt:387(搜「the model outlines a series of intermediate steps」) · text/14-fm-introduction.txt:524(搜「score = cosine_similarity(reference_vec, cand_vec)」) · text/14-fm-introduction.txt:582(搜「0.906,」)
主走查:两句语料、提示里的禁令、逐字复述的答案CHAPTER 8 Prompt Engineering for RAG Systemstext/15-fm-introduction.txt:185(搜「Do not just repeat words」) · text/15-fm-introduction.txt:240(搜「Retrieved Context: It reduces hallucinations」) · text/15-fm-introduction.txt:242(搜「Answer: Retrieval-Augmented Generation (RAG) is a technique」)
「思维链」:代码补的那一行结论同上text/15-fm-introduction.txt:374(搜「answer_text += f」) · text/15-fm-introduction.txt:425(搜「Model output」)
「查询改写」其实是字符串替换同上text/15-fm-introduction.txt:509(搜「query.replace(RAG」)
多提示集成选中了最短的那个同上text/15-fm-introduction.txt:789(搜「Prompt 2 output」) · text/15-fm-introduction.txt:795(搜「grounding answers in retrieved documents」)
带引用作答:手打的字符串同上text/15-fm-introduction.txt:1099(搜「answer = RAG reduces hallucinations by grounding answers in」)
结构化输出:模板、兜底分支、印出来的 JSON同上text/15-fm-introduction.txt:1189(搜「strictly in the following JSON format」) · text/15-fm-introduction.txt:1227(搜「except json.JSONDecodeError」) · text/15-fm-introduction.txt:1259(搜「grounding answers in retrieved documents」)

Footnotes

  1. 出处:「CHAPTER 7 Response Generation with LLM in RAG Systems」第 77 段(text/14-fm-introduction.txt:77,搜「Stuff method works well when documents are short」)。原文的说法是:这种方式在文档较短时管用,否则有撑爆模型标记上限的风险。代码里那一行把它写成了链的类型参数(text/14-fm-introduction.txt:159,搜「directly stuffs docs into prompt」)。

  2. 出处:「CHAPTER 8 Prompt Engineering for RAG Systems」第 219–226 段(text/15-fm-introduction.txt:222,搜「It reduces」)。这段语料写死在配方的示例区里,一共两句话;查询在第 232 段(text/15-fm-introduction.txt:232,搜「How does RAG reduce hallucinations?」)。

  3. 出处:同章第 240 段(text/15-fm-introduction.txt:240,搜「Retrieved Context: It reduces hallucinations」)与第 242 段(text/15-fm-introduction.txt:242,搜「Answer: Retrieval-Augmented Generation (RAG) is a technique」)。检索结果里句 B 在前、句 A 在后,而答案里句 A 在前、句 B 在后 —— 两行对照着看,复述这件事就无从辩解了。提示里那句禁令在第 185 段(text/15-fm-introduction.txt:185,搜「Do not just repeat words」)。

  4. 出处:「CHAPTER 7 Response Generation with LLM in RAG Systems」第 187 段(text/14-fm-introduction.txt:187,搜「it does not guarantee syntactically valid output」)。原文点名了三种真正能约束输出的机制(JSON 模式、函数调用、解析器级校验),并说生产环境应当依赖受约束的结构化输出接口,而不是只靠提示。这是全书最有工程价值的一句话。

  5. 出处:「CHAPTER 8 Prompt Engineering for RAG Systems」第 1189 段(text/15-fm-introduction.txt:1189,搜「strictly in the following JSON format」)。兜底分支在第 1227–1237 段(text/15-fm-introduction.txt:1227,搜「except json.JSONDecodeError」),它把问题、代码里的检索结果、模型的原始输出三样手工装进一个字典。顺带:这一整段代码用的是全角引号,照抄必然报错。

  6. 出处:同章第 1251 段(text/15-fm-introduction.txt:1251,搜「retrieved_context」)与第 1259 段(text/15-fm-introduction.txt:1259,搜「grounding answers in retrieved documents」)。

  7. 补充(不在书里,依据我们的 frontier 书架):今天主流的做法是把字段定义作为参数交给模型接口,再拿同一份定义去校验返回结果,而不是把格式写在提示里。 依据: shelf=ai-frontier-reference/vercel-ai-sdk#05-structured-output.md @1c6854096fbe9aa55ae59cfa2bdee03d55e95c8e 事实=那一章写着结构化输出做两件事:一是通过 responseFormat 把 schema 交给模型接口(告诉模型按这个 schema 输出),二是拿到结果后按同一份 schema 校验解析,不符合就报错。

  8. 出处:「CHAPTER 7 Response Generation with LLM in RAG Systems」第 734 段(text/14-fm-introduction.txt:734,搜「numbered_context += f[{i}] ({source}): {doc.page_content}」)与第 738 段(text/14-fm-introduction.txt:738,搜「cite them like [1], [2]」)。

  9. 出处:同章第 794 段(text/14-fm-introduction.txt:794,搜「architecture that combines the ability of large language models」)。同一份输出里的 sources 字段(第 796–808 段,text/14-fm-introduction.txt:802,搜「chapter7_RAG.txt」)是代码从标签里取出来拼的,不是模型写的 —— 这一半反而做对了。

  10. 出处:「CHAPTER 8 Prompt Engineering for RAG Systems」第 1099 段(text/15-fm-introduction.txt:1099,搜「answer = RAG reduces hallucinations by grounding answers in」)。上面那几行把提示拼进了一个变量(第 1087–1097 段,text/15-fm-introduction.txt:1095,搜「cite sources using their IDs like [1], [2]」),而这个变量之后再没被用过;函数直接返回了手打的字符串,输出与它逐字相同(第 1116 段,text/15-fm-introduction.txt:1116,搜「Additionally, it improves AI responses by combining document retrieval」)。

  11. 出处:同章第 372–374 段(text/15-fm-introduction.txt:374,搜「answer_text += f」)与第 427–429 段(text/15-fm-introduction.txt:425,搜「Model output」)。代码写的是:若模型输出里找不到 Final Answer: 这个字样,就把检索结果的第 1 名接到答案后面并冠上这个字样。输出里那一行恰好等于第 1 名(第 421 段,text/15-fm-introduction.txt:421,搜「Top 1: It reduces hallucinations」)。提示里的要求在第 346–350 段(text/15-fm-introduction.txt:348,搜「Write 2–3 bullet points of reasoning」)。 2

  12. 出处:同章第 509 段(text/15-fm-introduction.txt:509,搜「query.replace(RAG」)。这一节的正文承诺的是让模型生成不同措辞、同义词或拆解出的子查询(第 433 段,text/15-fm-introduction.txt:433,搜「alternative phrasings, synonyms, or decomposed sub-queries」)。

  13. 出处:同章第 787–795 段(text/15-fm-introduction.txt:789,搜「Prompt 2 output」)。三个提示的输出里,第 2 个最完整,第 1、3 个各只有一个短语;第四次调用「合成一个最好的」之后,最终答案是第 795 段那个短语(text/15-fm-introduction.txt:795,搜「grounding answers in retrieved documents」)—— 和最短的那两个一模一样。

  14. 出处:「CHAPTER 7 Response Generation with LLM in RAG Systems」第 387 段(text/14-fm-introduction.txt:387,搜「the model outlines a series of intermediate steps」)。原文说这种做法把推理引进 RAG 流程、让模型把中间步骤列出来,从而更透明可解释。提示那一句在第 500 段(text/14-fm-introduction.txt:500,搜「Think step by step and provide a clear, factual answer」);打分那两行在第 510 段(text/14-fm-introduction.txt:510,搜「reference_text = query」)与第 524 段(text/14-fm-introduction.txt:524,搜「score = cosine_similarity(reference_vec, cand_vec)」),挑最高分那一行在第 530 段(text/14-fm-introduction.txt:530,搜「best_answer, best_score = max(scored」)。五个候选与它们的分数印在第 580–620 段(text/14-fm-introduction.txt:580,搜「So the answer is RAG」),最高分 0.906 在第 582 段(text/14-fm-introduction.txt:582,搜「0.906,」)。五条候选没有一条写出中间步骤。

  15. 出处:「CHAPTER 7 Response Generation with LLM in RAG Systems」第 1659 段(text/14-fm-introduction.txt:1659,搜「metadata such as document source, author, timestamp」)。

  16. 出处:同章第 1733 段(text/14-fm-introduction.txt:1733,搜「enriched_answer」)与第 1771 段(text/14-fm-introduction.txt:1771,搜「A: RAG reduces」)。输出里那两句顺序反了,而且从句子中间断开 —— 因为代码是按英文句号切句的,而语料里到处是换行。

  17. 出处:同章第 818 段(text/14-fm-introduction.txt:818,搜「a cross-encoder is often used to re-score and re-order candidates」)与第 991 段(text/14-fm-introduction.txt:991,搜「final_answer」)。那个 final_answer 字段里三段话由分隔线隔开,内容几乎逐字相同

  18. 出处:同章第 9 段(text/14-fm-introduction.txt:9,搜「brand consistency」)。原文说安全的生成需要一个独立的架构层,与检索、排序、事实核查分开,用来落实隐私、安全与品牌一致性。全书此后再没有提过这一层。