RAG 流水线
RAG 流水线是用户查询从进入系统到返回答案的完整生命周期。把它建模为状态机,有助于处理重试、改写、多轮检索与失败兜底。
流水线状态机
[Receive Query]
│
▼
[Preprocess] ──▶ [Clarify] ──▶ 用户澄清
│
▼
[Retrieve] ──▶ [Empty?] ──▶ [Rewrite/Expand] ──▶ 再次 Retrieve
│ │
▼ ▼
[Re-rank] [Fallback]
│
▼
[Assemble Context]
│
▼
[Generate] ──▶ [Hallucination Check] ──▶ 后处理
│
▼
[Return Answer + Citations]
─── Agentic 模式下的内层循环 ───
[Generate] 在推理中发出检索请求 ──▶ [工具检索]
▲ │
└────────── [反思:继续 or 停止] ◀─┘2025 年后,流水线的关键变化是:Generate 不再只在末端出现一次。在 Agentic / 推理模式下,模型可以在推理过程中自主发起多次检索(把 Retriever 当工具调用),并在每次检索后反思“信息够不够、查询要不要改”。这一范式由 Search-R1、ReSearch 等工作用强化学习训练成型(见 Search-R1),工程落地时通常限制最大迭代轮数与 token 预算。
1. 查询接收(Receive Query)
- 支持原始文本、会话历史、多模态输入(图片、语音转写)。
- 附加 context:用户 ID、tenant、权限角色、时间、地理位置。
2. 查询预处理(Preprocess)
| 操作 | 目的 |
|---|---|
| 意图识别 | 判断是否需要检索,或可直接闲聊/拒绝 |
| 查询重写 | 把口语化 query 改成适合检索的表达 |
| 查询扩展 | 生成同义词、子问题,提高召回 |
| 敏感词过滤 | 防止检索到受限文档或生成违规内容 |
| 会话上下文压缩 | 把多轮对话提炼为当前检索需求 |
示例:
- 用户问:“这玩意儿怎么退?”
- 改写后:“Acme Corp 的退货政策是什么?”
3. 检索(Retrieve)
- 调用 dense、sparse 或 hybrid retriever。
- 应用 metadata 过滤(tenant、source、时间范围)。
- 返回候选 chunks,通常远多于最终进入 prompt 的数量。
空召回处理:
- 触发查询改写或扩展。
- 放宽 metadata 过滤。
- 如果仍无结果,进入 fallback:回答“未找到相关资料”。
检索质量自检(Corrective RAG 思路):CRAG(arXiv:2401.15884)提出在检索后加一个轻量评估器,把结果分为 Correct / Ambiguous / Incorrect 三档:Correct 直接用,Ambiguous 补充背景知识后再用,Incorrect 则丢弃并触发改写重检索。这把“检索失败兜底”从被动异常处理变成了流水线中的显式状态。到 2026 年,这一自检已内化为编排框架的标准节点(LangGraph 的 grading 节点、LlamaIndex 的 evaluator 组件);本主题 mini-demo 也用确定性的双通道一致性打分模拟了这个评分器(rag_mini/crag.py,见第 7 章)。
推理模型的查询生成:2025 年后的实践表明,推理模型生成的检索查询通常比“让 LLM 一次性改写”更贴合多步需求——因为它是在推理中途“知道自己缺什么”时发起的查询。代价是需要把检索工具 schema 与上下文协议设计好(返回哪些字段、截断多少、如何编号引用)。
4. 重排(Re-rank)
- 输入:检索 Top-K(如 50 或 100)。
- 输出:更精简的 Top-N(如 5 或 10)。
- 可加入业务规则:优先最新文档、优先权威 source、去重。
5. 上下文组装(Assemble Context)
- 按相关性或时间排序 chunks。
- 截断到模型上下文预算,保留系统 prompt 空间。
- 生成引用标记
[1]、[2],与 chunk 元数据绑定。
上下文排序技巧:
- 最相关的 chunk 放在 prompt 最前和最后。
- 相关性次之的放在中间,降低“中间位置信息丢失”问题。
6. 生成(Generate)
- Prompt 模板包含系统角色、参考资料、用户问题、输出格式要求。
- 模型流式输出答案与引用标记。
- 可设置
temperature较低,提高事实稳定性。
7. 后处理(Post-process)
| 检查 | 做法 |
|---|---|
| 引用校验 | 确认模型输出的 [1] 对应真实 chunk |
| 答案相关性 | 判断答案是否真正回答了 query |
| 幻觉检测 | 用 NLI 模型或 LLM self-check 验证答案是否被上下文支持 |
| 敏感内容过滤 | 再次过滤输出 |
8. 返回与观测(Return & Observe)
- 返回答案、引用、置信度、耗时。
- 记录完整 trace:query、rewritten query、retrieved chunks、reranked chunks、generated answer、latency、token usage。
失败模式与兜底
| 失败场景 | 兜底策略 |
|---|---|
| 检索空结果 | 查询改写 → 放宽过滤 → 回答“不知道” |
| 检索结果不相关 | 多路召回 → Reranker 过滤 → 降低置信度 |
| 模型生成偏离上下文 | 引用校验 + 后处理拒绝 |
| 延迟过高 | 超时后返回缓存结果或降级为纯检索列表 |
| 向量库故障 | 切换只读副本或 fallback 到关键词索引 |
小结
RAG 流水线不是单线程的一次调用,而是一个可以循环、分支、降级的状态机。设计时要为每个状态预留观测点与兜底路径,才能保证线上稳定。