13.8 生成阶段 —— 让 LLM 用上检索结果
检索和重排序完成了”找资料”的工作,但最终的质量取决于 LLM 怎么”用”这些资料。生成阶段的设计同样重要。
13.8.1 Prompt 模板设计
RAG 的 Prompt 模板通常包含四个部分:
1. 系统角色设定:告诉 LLM 它是谁。“你是一个专业的技术文档助手”和”你是一个通用的 AI 助手”,前者会让 LLM 更倾向于使用技术术语,回答更专业。
2. 检索到的文档内容:这是 RAG 的核心。通常放在用户问题之前,用特殊标记(如 """ 或 ---)分隔,让 LLM 清楚区分”参考资料”和”用户问题”。文档的顺序很重要——LLM 对 Prompt 开头和结尾的内容更”关注”(Lost in the Middle 现象),所以最相关的文档应该放在最前面和最后面。
3. 用户问题:用户原始的问题。
4. 指令约束:这是最容易被忽视但最关键的部分。好的指令约束包括:
- “请基于参考资料回答,不要使用你的训练数据中的知识”——防止 LLM 忽略检索结果,凭记忆回答。
- “如果参考资料不足以回答问题,请明确说’根据现有资料无法回答’,不要编造”——防止幻觉。
- “请在答案中标注引用来源,格式为 [来源 N]“——让用户能追溯信息。
- “请用中文回答”——语言控制。
13.8.2 引用来源
让 LLM 标注引用来源是 RAG 相比纯 LLM 的核心优势之一。实现方式有两种:
- Prompt 中标注:在每段参考资料前加编号(如
[1]、[2]),要求 LLM 引用时使用这些编号。简单但不太可靠——LLM 可能编造不存在的引用编号。 - 后处理验证:LLM 生成答案后,用另一个模型(或规则)验证每个引用是否真的对应到检索到的文档中的内容。这是更可靠的做法,但增加了系统复杂度。
13.8.3 处理检索失败
不是每次检索都能找到相关文档。常见失败场景和应对:
- 检索结果为空:用户的问题超出了知识库范围。策略:直接告诉用户”没有找到相关信息”,而不是让 LLM 凭记忆回答。
- 检索结果不相关:找到的文档跟问题不沾边。策略:设置相关性阈值,低于阈值的文档丢弃。如果丢弃后没有文档了,同上处理。
- 检索结果部分相关:有些文档相关,有些不相关。策略:重排序能有效过滤不相关文档;也可以在 Prompt 中告诉 LLM”如果某段参考资料与问题无关,请忽略它”。
13.8.4 流式生成
RAG 场景下流式生成(Streaming)有两个好处:用户体验好(逐字显示,不用等)、LLM 可以在生成过程中”看到”更多上下文。实现方式:调用 LLM API 时设置 stream=True,然后逐块返回内容。注意:流式生成时,引用标注通常在最后才出现——这让用户验证引用变得困难。一个折中方案是让 LLM 先生成答案,再追加引用列表。
13.8.5 上下文窗口管理
即使检索到的文档经过了重排序和过滤,总长度可能仍然超过 LLM 的上下文窗口。或者虽然没有超过,但太长会稀释关键信息。处理策略:
- 截断:只取 Top-N 个文档(N 通常 3-7),每个文档限制最大长度。
- 摘要压缩:用一个小模型先把每篇文档压缩成摘要,再把摘要塞进 Prompt。代价是摘要可能丢失细节。
- 层次化 Prompt:先让 LLM 用 Top-K 文档生成一个初步答案,再让 LLM 用这个初步答案 + 更多文档做细化。类似 Map-Reduce 的思路。
2026 年最佳实践:Prompt 模板 + 重排序 + 引用标注 + 检索失败处理,这四个环节缺一不可。
← 上一节:13.7 重排序 —— 提升精度的关键 | 下一节:13.9 第四代:AI 自己决定怎么搜(Agentic RAG) →