可运行的 jupyter notebook 仓库:https://github.com/tangpan360/RAG_Techniques_CN
目标:学习 RAG 这类 检索增强问答系统产品 的整体形态与关键原理。
方法:以 RAG 全流程为主线,把流程拆成若干环节,汇总每个环节常见的多种优化方案;每个环节都用为该学习目标专门设计的例子把关键行为"跑出来",通过实例去理解它如何设计、如何工作,以及在什么场景下最有效。
宏观:RAG 到底是什么?
RAG(Retrieval-Augmented Generation,检索增强生成)是一类把 信息检索 与 生成式模型 结合起来的系统:面对一个问题,系统先从外部知识源/资料库里检索出相关内容,再把这些内容作为上下文交给大模型生成回答,从而获得更准确 、更上下文相关 、更信息完整的输出。
这也是本仓库关注的核心:围绕这条"检索→生成"的主流程,提供一系列增强手段,去提升 准确性(accuracy) 、效率(efficiency) 与 上下文丰富度(contextual richness)。
系统框架:它由哪些模块拼起来?(我们当前学的在什么位置)
RAG 的系统框架不是"分层",而是一条清晰的端到端流程:离线索引(建库) + 在线问答(检索→生成),并且用可靠性与评估闭环把它变成"可长期迭代的产品"。
#mermaid-svg-bE7SnWDc1CCILz0o{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bE7SnWDc1CCILz0o .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bE7SnWDc1CCILz0o .error-icon{fill:#552222;}#mermaid-svg-bE7SnWDc1CCILz0o .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bE7SnWDc1CCILz0o .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bE7SnWDc1CCILz0o .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bE7SnWDc1CCILz0o .marker.cross{stroke:#333333;}#mermaid-svg-bE7SnWDc1CCILz0o svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bE7SnWDc1CCILz0o p{margin:0;}#mermaid-svg-bE7SnWDc1CCILz0o .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bE7SnWDc1CCILz0o .cluster-label text{fill:#333;}#mermaid-svg-bE7SnWDc1CCILz0o .cluster-label span{color:#333;}#mermaid-svg-bE7SnWDc1CCILz0o .cluster-label span p{background-color:transparent;}#mermaid-svg-bE7SnWDc1CCILz0o .label text,#mermaid-svg-bE7SnWDc1CCILz0o span{fill:#333;color:#333;}#mermaid-svg-bE7SnWDc1CCILz0o .node rect,#mermaid-svg-bE7SnWDc1CCILz0o .node circle,#mermaid-svg-bE7SnWDc1CCILz0o .node ellipse,#mermaid-svg-bE7SnWDc1CCILz0o .node polygon,#mermaid-svg-bE7SnWDc1CCILz0o .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bE7SnWDc1CCILz0o .rough-node .label text,#mermaid-svg-bE7SnWDc1CCILz0o .node .label text,#mermaid-svg-bE7SnWDc1CCILz0o .image-shape .label,#mermaid-svg-bE7SnWDc1CCILz0o .icon-shape .label{text-anchor:middle;}#mermaid-svg-bE7SnWDc1CCILz0o .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bE7SnWDc1CCILz0o .rough-node .label,#mermaid-svg-bE7SnWDc1CCILz0o .node .label,#mermaid-svg-bE7SnWDc1CCILz0o .image-shape .label,#mermaid-svg-bE7SnWDc1CCILz0o .icon-shape .label{text-align:center;}#mermaid-svg-bE7SnWDc1CCILz0o .node.clickable{cursor:pointer;}#mermaid-svg-bE7SnWDc1CCILz0o .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bE7SnWDc1CCILz0o .arrowheadPath{fill:#333333;}#mermaid-svg-bE7SnWDc1CCILz0o .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bE7SnWDc1CCILz0o .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bE7SnWDc1CCILz0o .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bE7SnWDc1CCILz0o .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bE7SnWDc1CCILz0o .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bE7SnWDc1CCILz0o .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bE7SnWDc1CCILz0o .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bE7SnWDc1CCILz0o .cluster text{fill:#333;}#mermaid-svg-bE7SnWDc1CCILz0o .cluster span{color:#333;}#mermaid-svg-bE7SnWDc1CCILz0o div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bE7SnWDc1CCILz0o .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bE7SnWDc1CCILz0o rect.text{fill:none;stroke-width:0;}#mermaid-svg-bE7SnWDc1CCILz0o .icon-shape,#mermaid-svg-bE7SnWDc1CCILz0o .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bE7SnWDc1CCILz0o .icon-shape p,#mermaid-svg-bE7SnWDc1CCILz0o .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bE7SnWDc1CCILz0o .icon-shape .label rect,#mermaid-svg-bE7SnWDc1CCILz0o .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bE7SnWDc1CCILz0o .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bE7SnWDc1CCILz0o .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bE7SnWDc1CCILz0o :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Eval
Guard
Online
Offline
数据源 PDF 网页 Markdown CSV DB
Load 统一为 Document
Clean Normalize
Chunking
Embeddings
Index Store
用户问题
Query Rewrite
Retrieve
Fuse Rerank
Context Building
Generate
最终回答
Reliability
Evaluation Monitoring
环节:Basic RAG(最小端到端闭环 / Baseline)
1.【Basic RAG】在 RAG 里的位置
Basic RAG 就是 RAG 的主干闭环,也是后面所有优化方案的"对照基线":
- 离线索引(Indexing):Load → Chunk → Embedding → Index/Store
- 在线问答(Query-time):Query → Retrieve → Context Building(最简)→ Generate → Answer
一句话:Basic RAG 是"离线把知识变可检索、在线把证据喂给模型生成答案"最基础的实现流程。
2.【Basic RAG】要解决 RAG 什么问题
- 先跑通"检索→生成"这一条主线:让回答来自证据,而不是来自"模型的自由发挥"。
- 先把 baseline 固定下来:否则你做任何优化都没法回答"到底提升了多少"。
- 把优化对齐到流程插槽 :后面每种优化(chunk/query/rerank/compression/reliable/eval/GraphRAG...)都应该能回答:
- 提升:相关性 / faithfulness / correctness
- 代价:成本 / 延迟 / 复杂度
3.【Basic RAG】是通过几类什么设计,分别如何解决的问题
Basic RAG 只需要抓住 7 个"最小设计点"(后面所有优化,都是在这些插槽上做增强):
-
【设计 1:统一数据协议(Document)】
- 怎么做 :Loader 把不同来源(md/pdf/csv/json...)统一成
Document(text, metadata)。 - 解决:后续的 chunk/embedding/index/retriever/prompt 都围绕统一输入输出工作。
- 怎么做 :Loader 把不同来源(md/pdf/csv/json...)统一成
-
【设计 2:切分(Chunking)】
- 怎么做:把长文切成可检索粒度(baseline 先用最常见的规则切分)。
- 解决:让"证据"以可召回的片段形态存在,为后续 chunk 优化留下对照。
-
【设计 3:向量化(Embeddings)】
- 怎么做:chunk → vector。
- 解决:让检索具备语义相似度能力,而不是纯关键词匹配。
-
【设计 4:索引与存储(Index/Store)】
- 怎么做 :向量库保存
vector + chunk + metadata,支持 Top-k 检索。 - 解决:把"外部知识"变成一个可查询的系统组件。
- 怎么做 :向量库保存
-
【设计 5:检索接口(Retriever + Top-k)】
- 怎么做:把"怎么检索"封装成 retriever(k、过滤、相似度计算)。
- 解决:后续 fusion/rerank/route 都能在不改生成链路的前提下替换检索策略。
-
【设计 6:上下文构造(最小 Context Building)】
- 怎么做:把 Top-k chunks 组织成"证据包"放进 prompt(baseline 先不做复杂压缩/抽段)。
- 解决:让生成阶段看到的不是"原文全集",而是"与问题相关的证据集合"。
-
【设计 7:回答形态(Answer + 最小引用/来源)】
- 怎么做:回答尽量携带来源线索(至少能追溯到 chunk 的 metadata/source)。
- 解决:为后续 reliable RAG 与评估闭环提供可观测对象(证据、引用、命中情况)。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
这一节的目的只有一个:让你看到 Basic RAG 的每个步骤在实例里"长什么样",从而后面做优化时你知道要改哪个插槽。
例子
- 知识库:一份《公司员工手册》(含报销、请假、权限、差旅等章节)+ 一份《产品 FAQ》(含版本、限制、定价)
- 问题集(示例 3 个) :
- Q1(事实型):"报销的最高额度是多少?需要哪些材料?"
- Q2(综合型):"差旅政策里对机票与酒店的限制如何组合生效?"
- Q3(不可回答型):"下个月公司是否会裁员?"
Turn 0:离线索引(把资料变成可检索系统)
你 "跑 baseline"(概念上等价步骤),会依次看到:
-
Load → Document :把手册与 FAQ 转成
Document(text, metadata)(metadata 里能追溯来源:手册/章节/页码等)【设计 1:Document】你会在输出里看到
page_content与metadata["source"]。 -
Chunking :把
Document切成 chunks(你会看到每个 chunk 像"一段可引用的证据")【设计 2:Chunking】此时不追求最优,只要可复现,后面才能对照"怎么切更好"。
-
Embeddings + Index :chunk → vector → 写入向量库(从这一步起它"可检索"了)
【设计 3:Embeddings】
【设计 4:Index/Store】
此时你得到一个可查询对象(vector store / retriever 的底座)------这一步完成后,"离线部分"就算结束。
Turn 1:在线问答(Q1:事实型)
你输入问题 Q1:
-
Retrieve :取 Top-k chunks(你会看到命中的证据片段)
【设计 5:Retriever】
-
Context Building(最简) :把 Top-k chunks 拼成"证据包"
【设计 6:Context Building】
-
Generate :LLM 生成回答
【设计 7:Answer】回答里至少能追溯证据来源(最小形态:输出中附带
source或引用的片段标识)。
Turn 2:在线问答(Q2:综合型)
你输入问题 Q2,同样跑:
- Retrieve → Context Building → Generate
你会在 baseline 里观察到一个典型现象:
综合型问题往往需要多个 chunks 联合支撑;baseline 的表现会暴露后续优化的插槽(例如:chunk 粒度是否能覆盖关键信息、Top-k 是否足够、是否需要 rerank/扩窗)。
Turn 3:在线问答(Q3:不可回答型)
你输入问题 Q3:
- baseline 仍会按 Retrieve → Generate 跑一遍
你要观察的不是"它说得多漂亮",而是:
检索证据是否真的包含答案 ,以及回答是否能明确区分"证据里有/没有"。
这会自然引出后续部分的优化方向(Reliable RAG / faithfulness / refusal)。
5.【Basic RAG】总结
- 这一部分的目标不是"把效果做到最好",而是把 RAG 的端到端流程跑通,并建立一个可复现 baseline。
- 你应带走的记忆点:
- RAG 的主干是"离线索引 + 在线问答"两段闭环
- 任何优化都必须能定位到流程插槽(chunk/query/retrieve/context/generate)
- 先有 baseline,才有资格谈提升与代价
环节:离线索引优化(Chunking & Indexing Quality)
1.【离线索引优化】在 RAG 里的位置
这一部分发生在 离线索引(Indexing / Ingestion) 阶段,核心目标是把资料处理成"更容易被检索命中的证据形态":
- 上游:原始资料(手册/FAQ/长文/制度/网页)
- 中游:清洗 → 切分/重写/增强 → embedding → 写入索引
- 下游:在线检索能拿到更完整、更不孤立、更可组合的证据 chunks
一句话:离线索引优化管的是"证据长什么样",它决定了在线检索的上限。
2.【离线索引优化】要解决 RAG 什么问题
当你只用最朴素的规则切分(例如按字符长度硬切)时,常见问题不是"检索算法不够强",而是证据本身不可用:
- 证据被切断:关键条件被拆到两个 chunk,Top-k 只拿到一半 → 回答缺条件或答错。
- 证据太碎/太长:太碎导致需要很多块才能拼完整;太长又把无关内容一起塞进来 → 上下文污染、成本上涨。
- chunk 缺语境:单独拿出来看不出属于哪章/哪个条款 → 检索命中了也难以正确使用。
- 同义表达导致召回差:文档里写"差旅补贴",用户问"出差津贴" → 即使检索做得对,索引侧也可以更友好。
- 长文结构复杂:目录/标题/定义/例外条款分散 → 需要让"可检索证据"更结构化、更可组合。
3.【离线索引优化】是通过几类什么设计,分别如何解决的问题
这一部分你不仅要知道"切出来长什么样",更要知道"怎么切出来的 "。
下面每个设计都用同一套视角描述:产物形态(你最终存进向量库的 chunk 长什么样) + 获取路径(规则/大模型/混合) + 最低必要字段(可追溯)。
先给一个统一的"可追溯 chunk"底座(不管你用哪种切分):
chunk_text:真正参与 embedding 的文本source_id:来源文档标识(哪份手册/哪页/哪版本)source_span:来源片段范围(例如页码/段落号/原文起止)section_path:章节路径(差旅政策 > 酒店住宿 > 2.3 住宿标准)- (可选)
proposition_id/proposition_type:命题编号与类型(规则/例外/阈值/审批)- (可选)
tags/keywords:便于结构检索或过滤的标签
我们把离线索引侧最常见、也最容易在实例里"跑出来"的优化归成 5 类:
-
【设计 1:选择合适的 chunk size(粒度权衡)】
- 产物形态:还是"原文片段",只是每段长度/重叠变了。
- 获取路径:纯规则(按 token/字符/句子数切;再加 overlap)。
- 解决:把系统从"明显不可用"拉回"可用区间",但不解决边界语义问题。
-
【设计 2:按语义边界切分(Semantic Chunking)】
- 产物形态:以"条款/小节/主题"作为 chunk 单元(更自洽)。
- 获取路径(常见三种) :
- 规则优先:解析 markdown/PDF/HTML 的结构(标题层级、编号条款、列表、表格)→ 以结构边界切
- 向量辅助:对相邻段落做 embedding,检测语义突变点(topic shift)作为边界
- 大模型裁决:给一段长文本,让模型输出分段点(更稳,但要控成本/控漂移)
- 最低必要字段 :
section_path+source_span(否则语义 chunk 很难"引用得像条款")。
-
【设计 3:命题化切分(Proposition Chunking)】
- 产物形态:不再是"原文段落",而是一条条"原子可组合命题"(更短、更结构化)。
- 获取路径(你关心的重点) :
- 规则可直接抽取:标题编号条款、列表项、表格每行 → 天然就是命题
- 大模型抽取(最常见):对"一个语义 chunk/一条条款"做信息抽取,输出命题列表(并绑定证据 span)
- 混合:先结构解析把文档切到条款级,再让模型只在"条款内部"抽命题(范围更小、可控性更强)
- 质量约束(否则命题会漂) :
- 每条命题必须带
source_span(能回到原文哪句/哪行) - 命题必须是"复述/抽象",不能引入原文没有的新阈值、新主体、新流程
- 后处理去重/归一(金额、城市等级、审批角色统一写法)
- 每条命题必须带
- 解决:提升"跨条款组合题"的稳定性(上限 + 例外 + 审批这类问题会明显受益)。
-
【设计 4:chunk 加上下文头(Contextual Chunk Headers)】
- 产物形态 :
header + chunk_text(头通常很短,告诉你"我从哪来/我是什么类型")。 - 获取路径 :
- 规则优先:从结构解析直接拿(文档名/章节/条款号/版本号)
- 大模型可选:只用于"压缩标题/生成短路径",不负责生成事实
- 解决:减少断章取义,让短 chunk(尤其命题)在检索命中后"能被正确解释"。
- 产物形态 :
-
【设计 5:文档增强再入库(Document Augmentation)】
- 产物形态:除了原 chunk,再存一组"增强字段"(摘要/关键词/同义短语/标签/结构化属性)。
- 获取路径 :
- 规则:词表/业务同义词、章节标签、正则抽取实体(金额/城市等级/审批角色)
- 大模型:生成章节摘要、关键词、同义问法;或把条款改写成更"问答友好"的表达
- 混合:规则抽实体 + 模型补同义/摘要(更稳)
- 解决:对齐"用户问法 vs 文档写法",尤其是同义词、口语化问法与结构化条款之间的差距。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子
- 知识库:一份《公司员工手册》(报销/差旅/审批/例外条款)
- 目标问题(同一个问题贯穿) :
- Q:"出差住酒店的报销上限是多少?有哪些例外?需要什么审批?"
这个问题的特点是:答案通常分散在"标准上限条款""例外条款""审批要求"三个位置,特别容易被切分策略影响。
Turn 1:Baseline 切分(字符硬切)带来的典型现象
你用最朴素的 chunking(按长度切)入库后检索 Q,Top-k 可能长这样:
- chunk A:只包含"上限 600/晚"但缺少"城市等级/旺季例外"
- chunk B:包含"例外条款"但缺少"触发条件"
- chunk C:包含"审批要求"但没有"它在差旅章节中"的语境
你会看到的结果是:要么回答不完整(漏例外/漏审批),要么拼错(把例外条件套错到所有情况)。
(注意:这不是模型笨,而是证据被切得不可用。)
Turn 2:改 chunk size(设计 1)------先把"完整性 vs 噪声"调到一个可用点
你把 chunk size 调大一点并加少量 overlap:
- 原来"上限条款"的关键限定条件更可能落在同一个 chunk 里
- 但代价是:每个 chunk 携带更多无关句子,Top-k 里噪声也会上升
此时你会看到 Top-k 的变化往往是:
- 命中"上限条款"的 chunk 更完整了(更容易包含"适用范围/限定条件")
- 但"例外条款"和"审批要求"仍可能因为切分边界不友好而丢失关键条件
这说明:chunk size 只能把系统从"明显不可用"拉回"勉强能用",要想更稳定,必须处理"边界在哪里切"。
Turn 3:按语义边界切分(设计 2)------让 chunk 成为"可引用证据块"
你改成优先在"条款/小节/标题边界"切分(例如按 2.3 酒店住宿标准、2.4 例外情形、2.5 审批要求 的边界切)。
这里的"边界"通常不是拍脑袋来的,而是先把文档结构解析出来:
-
如果是 markdown/HTML:标题层级、列表、表格天然可解析
-
如果是 PDF:先做版面/段落识别,把"标题/编号条款/正文"分开
-
解析不到结构时,才考虑用"相邻段落语义突变"或让模型输出分段点作为 fallback
-
你期待检索命中的不再是"随机截断的一段话",而是天然自洽的一条规则/一组规则
此时同样问 Q,Top-k 更可能变成:
- chunk A:完整的"酒店住宿标准(含城市等级/金额上限/适用范围)"
- chunk B:完整的"例外情形(触发条件 + 允许的上限/处理方式)"
- chunk C:完整的"审批要求(谁批/什么时候批/需要什么材料)"
你会观察到:回答开始"像人一样引用条款",并且更容易把"标准 + 例外 + 审批"拼成一段完整答复。
Turn 4:命题化切分(设计 3)------把"规则"拆成可组合的原子事实
语义 chunking 已经能用,但制度类文本常见一个问题:一个条款里同时包含多个条件、多个例外、多个阈值。
你进一步把条款拆成命题(每条命题都尽量是"一个条件→一个结论/一个约束")。
关键点:命题不是"凭空总结",它需要一条可操作的获取路径。常见做法是 结构优先 + 模型抽取 + 追溯约束:
- 步骤 A(规则):先把文档切到"条款级语义块"(上一 Turn 的产物),每次只处理一个条款/小节
- 步骤 B(大模型抽取) :对该条款做信息抽取,输出一个命题列表(每条必须绑定原文证据)
- 你可以把模型输出想象成这种结构:
- 命题文本:
一线城市酒店上限 600/晚 - 命题类型:
阈值/规则/例外/审批 - 证据:该命题对应原文的哪一句/哪几句(
source_span)
- 命题文本:
- 你可以把模型输出想象成这种结构:
- 步骤 C(后处理):去重、金额/城市等级归一、把"审批链路"拆成单独命题
这样你才能保证:命题是"可组合的原子事实",同时又能回到原文核对(不会引入新的金额/条件)。
例如把"酒店住宿标准"拆成(示意):
- P1:一线城市:上限 600 元/晚
- P2:二线城市:上限 450 元/晚
- P3:旺季或会议城市:需主管审批后可上浮至 800 元/晚
- P4:报销必须提供发票与订单信息
把"例外情形"拆成:
- E1:因会务统一订房导致超标:需提供会议通知与订单凭证
- E2:临时改签导致超标:需在报销单备注原因并补充截图
把"审批要求"拆成:
- A1:超标需主管审批;超过 800 需总监审批
这时检索 Q 的 Top-k 很可能直接命中若干条命题(P1/P2/P3 + A1 + 相关例外),而不是命中一个"杂糅大段落"。
你得到的提升是:组合答案更稳(尤其当问题问"上限 + 例外 + 审批"这种跨条款组合题)。
Turn 5:chunk 加上下文头(设计 4)------让证据不再"断章取义"
命题化的代价是:单条命题很短,天然缺语境。
你给每个 chunk(尤其是命题 chunk)加上上下文头。这个头信息通常不需要模型生成,直接来自结构解析(文档名/版本/章节/条款号),例如:
《员工手册》> 差旅政策 > 酒店住宿 > 2.3 住宿标准(2026-07 修订)
或:
《员工手册》> 差旅政策 > 2.4 例外情形
同样问 Q,你会发现即使检索命中的是短命题:
- LLM 也更容易正确解释"这是差旅政策,不是福利政策"
- 也更容易在回答里给出可信的引用锚点(章节/条款编号)
这一步通常不会显著改变"命中哪些 chunk",但会显著改变:命中了以后能不能用对。
Turn 6:文档增强再入库(设计 5)------处理"用户问法"和"文档写法"不一致
现在我们把问题换一种说法(仍然问同一件事):
- Q':"出差酒店补贴/津贴怎么算?超标要不要审批?有哪些特殊情况?"
如果手册里只写"住宿标准/报销上限",不写"补贴/津贴",就可能出现召回下降。
你在入库时为章节/命题补充"关键词/同义表达/简短摘要/标签"。这些增强字段的获得方式通常是"规则 + 模型"两条腿:
- 规则:把手册里的"差旅/住宿/报销/审批"等词表、金额、城市等级、角色名抽出来当标签
- 模型:生成同义问法、口语化短语、章节摘要(注意仍要绑定原文,不要发明新规则)
例如:
- 关键词:住宿标准、酒店上限、报销上限、差旅补贴(同义)、酒店津贴(同义)
- 摘要:说明标准上限、例外条件与审批链路
你会看到的变化是:Top-k 更容易把"住宿标准/审批要求/例外情形"一起召回出来,从而让回答在不同问法下保持稳定。
5.【离线索引优化】总结
- 这部分在 RAG 里管的是"证据形态":你在离线阶段把 chunk 做得越可检索、可引用、可组合,在线阶段越省力。
- chunk size 解决的是粗粒度权衡 ,但真正决定稳定性的通常是:语义边界 与命题化可组合性。
- 上下文头让证据可用 (防断章取义),入库增强让问法更鲁棒(对齐同义与结构)。
环节:Query 理解与改写(Query Transformation)
1.【Query 理解与改写】在 RAG 里的位置
这一部分发生在 在线问答(Online QA) 的最前面:用户问题进来后,先经过 query 的"理解/规范化/扩展/拆解",再把结果交给检索。
- 上游:用户原始问题(口语化、缺省信息、带上下文、可能多意图)
- 中游:Query Transformation(本节)
- 下游:Retriever / Reranker / Context Building / Generate
一句话:检索不是在搜"原句",而是在搜"你真正想问的那件事"。
2.【Query 理解与改写】要解决 RAG 什么问题
哪怕你的索引做得很好,在线检索仍然会因为"问法"而失准。最常见的失败模式是:
- 信息缺省:用户不说城市等级、时间、生效版本,但答案依赖这些条件。
- 同义/口语化:用户说"补贴/津贴/标准",文档写"住宿标准/报销上限"。
- 多意图混在一句话:一个问题里同时问上限、例外、审批、材料。
- 需要推导/合并约束:例如"住两晚""旺季""会议统一订房"等,需要先把条件抽出来再检索。
- 需要范围限定:同一个"审批"在差旅、采购、用章都有,必须先决定"在哪个域里搜"。
3.【Query 理解与改写】是通过几类什么设计,分别如何解决的问题
这部分的关键同样不是"改成什么样",而是"怎么得到这个改写"。常见做法可以归为 5 类(可以单用,也常组合用):
-
【设计 1:Query 规范化(Normalization)】
- 产物形态:把口语化问题改成更检索友好的"标准问句/关键词集合"。
- 获取路径:规则(同义词词表、大小写/符号处理) + 模型(把意图与关键约束抽出来)。
- 解决:同义问法、噪声词、非标准表达导致的召回波动。
-
【设计 2:约束抽取与补全(Constraint Extraction & Slot Filling)】
- 产物形态 :
intent + slots(例如城市等级/是否旺季/是否统一订房/金额阈值/审批角色)。 - 获取路径:模型抽取为主;必要时基于对话上下文或用户画像补全默认值(也可提示用户补充)。
- 解决:信息缺省导致的"搜错范围 / 引错条款"。
- 产物形态 :
-
【设计 3:查询拆解(Decomposition)】
- 产物形态:把一个多意图问题拆成多个子查询(上限/例外/审批/材料)。
- 获取路径:模型进行意图分解;也可以用规则把"并且/以及/同时"之类连接词拆开。
- 解决:一个 query 太复杂导致 Top-k 被单一子意图占满,漏掉其他证据。
-
【设计 4:查询扩展(Multi-Query / HyDE / Step-back)】
- 产物形态:一组等价或互补的检索 query(同义扩展、假设性答案、抽象上位问法)。
- 获取路径:模型生成多 query 或 HyDE 文本;规则提供词表扩展与短语组合。
- 解决:同义表达、术语不一致、长尾问法导致的低召回。
-
【设计 5:自查询(Self-Query / 结构化过滤)】
- 产物形态 :
text_query + metadata_filters(例如限定policy=差旅、doc_version=2026-07)。 - 获取路径:模型把自然语言翻译成可执行的过滤条件;规则校验与兜底。
- 解决:同词多义、跨域冲突、版本/部门差异导致的"搜到不该看的证据"。
- 产物形态 :
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用上一节)
- 知识库:《公司员工手册》(含差旅政策:住宿标准/例外情形/审批要求)
- 用户原始问题(带口语+多意图) :
- Q0:"我下周去上海开会,酒店能报多少?如果超了怎么办?要找谁批?需要准备啥?"
你会用同一个 Q0 连跑 5 个 Turn。每个 Turn 都强调"这一步怎么得到",并观察它如何改变检索命中。
Turn 1:只做规范化(设计 1)
怎么得到:
- 规则把"能报多少/超了怎么办/找谁批/准备啥"映射到手册常用表述:
报销上限/例外/审批/材料 - 模型把口语改成一个更规整的检索句(不引入新事实)
产物(示意):
- Q1:"差旅 酒店 住宿 报销上限 例外 审批 材料"
你会看到的 Top-k :更容易稳定命中 住宿标准/审批要求/例外情形 三块,但仍可能"抓不住上海属于哪类城市、会议是否属于例外触发条件"。
Turn 2:抽取约束并补全(设计 2)
怎么得到:模型从 Q0 中抽 slots(把"上海""开会""下周"变成约束),并把它们写进检索 query 或 metadata 里。
产物(示意):
intent: 查住宿报销标准slots:{ city: 上海, scenario: 会议, time: 下周 }
你会看到的 Top-k:更容易命中"城市等级对应的金额阈值"与"会议/旺季等情形是否触发例外条款"的相关段落。
Turn 3:把多意图拆成子查询(设计 3)
怎么得到:模型把 Q0 的意图拆成 4 个子问题(每个子问题都尽量单一)。
产物(示意):
- qA: "上海 酒店 住宿 报销 上限"
- qB: "住宿 超标 允许情形 例外 条款"
- qC: "住宿 超标 审批 角色 流程"
- qD: "报销 需要 材料 发票 订单 会议通知"
你会看到的 Top-k:每个子 query 都更"尖",证据覆盖更完整;同时你也得到了一个更清晰的答案拼装顺序(上限 → 例外 → 审批 → 材料)。
Turn 4:做扩展检索(设计 4:Multi-Query / HyDE / Step-back)
怎么得到:
- Multi-Query:模型生成若干等价问法("住宿标准/酒店上限/差旅补贴")
- HyDE:模型先写一段"可能的答案样子"(注意只用于检索,不直接当答案)
- Step-back:模型生成一个更抽象的上位问法("差旅住宿报销政策有哪些约束")
你会看到的 Top-k:召回更鲁棒,尤其当用户问法偏口语、而文档偏制度化时;但要注意控制扩展的数量,否则会拉进噪声。
Turn 5:做 Self-Query(设计 5:结构化过滤)
怎么得到:模型把 Q0 翻译成过滤条件(例如限定只搜差旅政策、限定最新版本),规则层对过滤条件做校验(不存在的字段直接丢弃/降级)。
产物(示意):
text_query: "酒店住宿 报销 上限 例外 审批 材料"filters:{ policy: 差旅, doc_version: 2026-07 }
你会看到的 Top-k:明显减少"审批"被召回到别的域(采购/用章)的概率;同时能避免旧版本条款混入导致的冲突答案。
5.【Query 理解与改写】总结
- 这部分是在线侧的第一个"纠偏阀":它决定检索到底在搜什么,能显著影响召回覆盖与噪声。
- 你要记住 5 类手段的分工:
- 规范化:稳住同义与口语
- 约束抽取:补全缺省,避免搜错范围
- 拆解:保证多意图证据覆盖
- 扩展:提升召回鲁棒性(但要控噪声)
- Self-Query:用结构化过滤处理跨域/版本冲突
环节:在线检索增强(Retrieve 策略 / Fusion / Rerank / 多样性 / 层次检索)
1.【在线检索增强】在 RAG 里的位置
这一部分发生在 Query 已经被改写/拆解/过滤之后,进入检索执行阶段:
- 上游:Query Transformation 的产物(可能是一组 query + filters)
- 中游:Retrieve(召回候选)→(可选)Fusion →(可选)Rerank / 多样性选择 → 输出最终 top-k
- 下游:Context Building(扩窗/抽段/压缩/去冗余)→ Generate
一句话:这部分决定"你最终给 LLM 的证据集合长什么样"。
2.【在线检索增强】要解决 RAG 什么问题
这一环节要解决的不是"有没有命中",而是"命中得是否足够好、足够全、足够干净":
- 召回不全:向量检索擅长语义,但对数字/专有名词/编号条款可能不敏感;BM25 相反。
- 候选不准:top-k 里混进"看起来相关但不回答问题"的段落。
- 重复/同质:知识库很稠密时,top-k 可能返回很多几乎一样的 chunk,浪费窗口。
- 长文结构导致的漏检:真正答案在某个章节深处,纯相似度检索容易抓到"概述"但漏掉"细则/例外"。
- 成本与窗口约束:你不能无限拉取候选,只能在有限预算里把证据集做得更优。
3.【在线检索增强】是通过几类什么设计,分别如何解决的问题
把常见的检索增强方案映射到"检索插槽",可以归纳为 5 类设计(也是下面实例会依次跑的 Turn):
-
【设计 1:基础召回(dense top-k / BM25 top-k / MMR)】
- 怎么得到 :
- dense:用 query embedding 做近邻搜索得到 top-k
- BM25:倒排/统计结构对关键词打分得到 top-k
- MMR:在候选里做"相关性 + 多样性"的折中选择
- 解决:建立可控 baseline,并对"语义命中 vs 关键词命中 vs 去重复"做最小对照。
- 怎么得到 :
-
【设计 2:融合检索(Fusion Retrieval:dense + BM25)】
- 怎么得到:分别取 dense top-k 与 BM25 top-k,再按融合规则(例如分数归一化、加权、或 RRF)合并排序。
- 解决:同时覆盖"语义相近"与"关键词精确命中"的召回盲区。
-
【设计 3:重排(Reranking)】
- 怎么得到:先"多取候选"(例如 top-20/50),再用 reranker(cross-encoder 或 LLM 打分)对候选逐个打分并选 top-n。
- 解决:把"真正回答问题的证据"推到最前面,降低噪声。
-
【设计 4:多样性选择(Dartboard / 贪心覆盖)】
- 怎么得到:在候选集上用贪心/距离约束,选出 top-k,使其"既相关、又彼此尽量不重复"。
- 解决:稠密知识库下的重复召回,让有限窗口装下更多互补证据。
-
【设计 5:层次检索(Hierarchical Indices)】
- 怎么得到:先检索"章节摘要/目录层",定位相关章节,再在该章节下钻检索"细则/例外/审批"。
- 解决:长文结构下的漏检与"只命中概述不命中细则"的问题。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册)
- 知识库:《公司员工手册》(差旅政策:住宿标准/例外情形/审批要求)
- 问题(多意图) :
- Q:"上海出差住酒店能报多少?超了怎么办?要找谁批?需要什么材料?"
为了让检索策略差异"跑出来",你只需要观察两件事:
- 召回覆盖:上限条款、例外条款、审批要求、材料要求是否都在最终 top-k 里出现
- 证据纯度:top-k 里有多少段落是"看起来相关但不回答"的噪声/重复
Turn 1:只用 dense top-k(设计 1 的 baseline)
怎么跑:把 query 做 embedding → 向量库 top-k。
你会看到的现象(典型):
- 能命中"差旅/住宿"相关段落,但对"600/晚、条款编号、审批阈值"等细粒度数字/关键词,命中不稳定
- top-k 可能被"差旅概述/原则"占位,真正回答"上限/例外/审批"的细则不一定排前
Turn 2:换成 BM25 top-k + MMR(仍属于设计 1)
怎么跑:
- BM25:用关键词(上海/酒店/住宿/报销/上限/审批/材料)做倒排检索
- MMR:在候选里选 top-k,避免返回一堆几乎一样的"住宿标准概述"
你会看到的变化:
- BM25 更容易命中带数字/编号的条款(例如"上限 600/晚""2.3/2.4")
- MMR 让最终 top-k 更"分散":更可能同时包含"标准 + 例外 + 审批 + 材料"四类证据,而不是四段相似概述
Turn 3:做 Fusion Retrieval(设计 2:dense + BM25 融合)
怎么跑:
- 先取 dense top-20(语义)与 BM25 top-20(关键词)
- 再做融合排序(最常见的直觉是:两路都觉得相关的,优先;只被一路命中的,往后排)
你会看到的变化:
- dense 把"例外情形(会议/旺季/统一订房)"这类语义相关段落带回来
- BM25 把"金额/阈值/编号条款/审批角色"这类关键词段落带回来
- 融合后,最终 top-k 的覆盖面明显更稳(尤其在"口语问法 + 条款写法"差距大时)
Turn 4:对 Fusion 的候选做 Reranking(设计 3)
怎么跑:
- 先从 Fusion 取回更大的候选池(例如 30-50 段)
- reranker 对每段打分,选 top-n(例如 6-8 段)作为最终证据
你会看到的变化:
- "看起来相关但不回答"的段落会被压下去(例如只讲差旅原则、不含上限/审批细则)
- 真正能回答四个子意图的段落更容易排到前面
你可以把 reranking 理解成一句话:把检索从"相似度排序"升级为"是否能回答该问题的排序"。
Turn 5:在候选上做 Dartboard/贪心多样性选择(设计 4)
怎么跑:在 Turn 4 的候选里再加一道"去重复"的贪心选择:
- 每次挑一个最相关的
- 然后对已选内容相似度太高的候选降权/剔除
- 直到选满 top-k
你会看到的变化:
- 在知识库内容高度相似(很多段落都重复"住宿标准原则")时,最终 top-k 更"互补"
- 你更可能拿到:标准条款 1 段 + 例外条款 1 段 + 审批条款 1 段 + 材料条款 1 段,而不是四段"标准条款改写版"
Turn 6:用层次检索解决"长文深处细则漏检"(设计 5)
怎么跑(最小思路):
- 先检索"章节级摘要/目录节点",定位到
差旅政策 > 酒店住宿 - 再在该章节下做第二次检索,专门找"上限/例外/审批/材料"
你会看到的变化:
- 比起一次性全库相似度检索,它更稳地把你带到"正确章节",再抓到细则
- 特别适合"员工手册/制度/年报"这种层级清晰的长文
5.【在线检索增强】总结
- 这一环节的目标是:在有限 top-k 与有限窗口下,拿到覆盖足够全、排序足够准、重复足够少的证据集合。
- 你应带走的对应关系:
- 召回不全 → Fusion(dense+BM25)
- 候选不准 → Reranking
- 重复同质 → MMR / Dartboard
- 长文漏检 → Hierarchical Indices
环节:Context Building(检索后上下文增强:RSE / 扩窗 / 压缩)
1.【Context Building】在 RAG 里的位置
这一环节位于:
- 上游:Query Transformation → Retrieve / Fusion / Rerank 得到候选
Document[] - 中游:Context Building(本节:扩窗/抽段/压缩/去冗余/排序)
- 下游:把最终上下文塞进 prompt → Generate
一句话:检索决定"拿到哪些证据",Context Building 决定"把证据怎么喂给模型"。
2.【Context Building】要解决 RAG 什么问题
你在检索后会遇到的常见痛点,不是"证据不存在",而是"证据形态不适合直接喂给 LLM":
- 命中很碎:top-k 只命中一两句,关键限定条件在前后段落 → 回答不完整或误用条件。
- 上下文缺桥梁:例外条款与触发条件分开写,中间夹着解释段 → 只拿到例外结论,没拿到触发条件。
- 窗口不够:候选很多,但你只能塞进有限 token → 要么漏关键证据,要么塞进噪声。
- 重复与顺序:同义/重复段落浪费窗口;乱序拼接让模型更难"按条款理解"。
3.【Context Building】是通过几类什么设计,分别如何解决的问题
这一环节可以归纳为 4 类设计:
-
【设计 1:最简拼接(Baseline Context)】
- 怎么得到:取回 top-k chunks,按 score 排序,直接拼接成 context。
- 解决:建立基线,暴露"碎片命中/缺条件/窗口污染"等问题。
-
【设计 2:window-around-chunk(命中后扩窗补邻居)】
- 怎么得到:对每个命中 chunk,按原文顺序补回前后 (w) 个邻居 chunk(或补回固定 token 范围)。
- 工程前提 :需要 chunk 有稳定的
source_span/顺序编号,能找到"邻居"。 - 解决:把"关键限定条件"补齐,让证据更完整。
-
【设计 3:RSE(Relevant Segment Extraction:连续段抽取)】
- 怎么得到 :
- 先对同一篇文档的所有 chunks 打相关性分(可用 reranker 或 embedding cosine)
- 在序列上找连续高分区间(segment),按长度预算输出 1~N 个连续段
- 工程前提(常见工程约束) :通常要求
chunk_overlap=0,方便把连续 chunk 拼回连续段。 - 解决:把"碎片命中"变成"可阅读的连续证据段",并补回夹在中间的重要 chunk。
- 怎么得到 :
-
【设计 4:Contextual Compression(压缩/过滤)】
- 怎么得到:先取回较多候选 chunks,再用 compressor 对每段进行"只保留与问题相关的句子/要点",或直接过滤掉不相关段。
- 实现路径:规则过滤(关键词/阈值/章节过滤) + 模型压缩(抽取相关句、去掉噪声)。
- 解决:在窗口/成本约束下,把上下文的"相关信息密度"拉高。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子
- 知识库:《公司员工手册》差旅政策(住宿标准/例外情形/审批要求)
- 问题 :
- Q:"上海出差住酒店能报多少?哪些情况可以超标?超标需要谁审批?要准备什么材料?"
这类问题最容易出现"碎片命中":你命中到一句"可上浮至 800",但触发条件在上一段;命中到"需主管审批",但"超过 800 需总监审批"在下一段。
Turn 1:Baseline 直接拼 top-k(设计 1)
怎么跑:检索(可能带 rerank)→ 取 top-6 → 直接拼接。
你会看到的 context 形态(典型):
- 一段"住宿标准概述"
- 一段"审批流程概述"
- 一段"例外情形结论句"
问题暴露:
- "上浮到多少/在什么条件下上浮/审批阈值"经常被拆散
- LLM 容易把"例外结论"误推广到所有情况(因为缺触发条件)
Turn 2:window-around-chunk 补邻居(设计 2)
怎么跑:
- 对每个命中 chunk,补回前后各 1~2 个邻居 chunk(按
source_span顺序) - 再把这些 chunk 去重、按原文顺序拼回 context
你会看到的变化:
- 例外条款前后的"触发条件/限定条件"被补回来了
- 同一条款更像一段完整可读的证据(而不是一句孤立结论)
你会直观看到:上下文更长了,但"关键条件缺失"的问题明显缓解。
Turn 3:RSE 抽连续段(设计 3)
怎么跑(一个最小可用思路):
- 对手册里"差旅政策"相关的所有 chunks 打相关性分(embedding cosine 或 reranker)
- 你会发现高分 chunk 通常会在文档中"成簇聚集"
- 在序列上找到一个或两个连续高分区间,把它们拼成 1~2 段连续 segment 输出(受长度预算控制)
你会看到的变化:
- context 变成了"连续段落",读起来像原文的一段条款
- 原本夹在两段高分 chunk 中间的"解释/限定"会被自动带上(这是 RSE 的关键收益)
相比扩窗,RSE 更像是:先确定"应该读哪一段原文",再把那一段完整搬进来。
Turn 4:Contextual Compression 提升信息密度(设计 4)
怎么跑:
- 先取回较多候选(例如 top-30)
- 对每个候选做压缩:只保留能回答 Q 的句子(金额阈值、触发条件、审批角色、材料清单)
- 再把压缩后的片段拼成最终 context(严格卡 token 预算)
你会看到的变化:
- context 变短,但"可回答信息密度"变高
- 当候选里混入噪声(差旅原则/文化宣导)时,压缩能把这些句子剔掉或大幅缩短
这一步会把系统从"有证据但塞不下/塞不干净",推向"证据更精炼、更适配窗口"。
5.【Context Building】总结
- 这一环节解决的是:同样的候选证据,喂法不同,效果可以差一档。
- 你应带走的三句对照:
- 扩窗:命中后补邻居,修"缺条件"
- RSE:从碎片命中恢复成"连续段",修"缺桥梁/缺上下文"
- 压缩:把上下文做"高密度",修"窗口/成本约束"
环节:Reliable RAG(可靠性与护栏:相关性过滤 + groundedness 检查 + 证据高亮 + 拒答)
1.【Reliable RAG】在 RAG 里的位置
这一环节位于 Retrieve / Context Building 之后、最终回答输出之前,它做的不是"再找更多证据",而是对整个链路做一次质量闸门:
- 上游:你已经拿到候选证据(并且已经扩窗/抽段/压缩过)
- 中游:可靠性检查(本节)
- 下游:输出"带证据的回答",或输出"基于证据无法回答"的拒答/澄清
一句话:Reliable RAG 管的是"能不能回答、能回答到什么程度、以及如何证明你没瞎编"。
2.【Reliable RAG】要解决 RAG 什么问题
当你把检索、重排、上下文拼装都做得不错之后,系统仍然会在这些场景里翻车:
- 证据不相关但看起来像相关:top-k 里混进了"同主题但不回答问题"的段落。
- 证据不足:证据里缺关键条件/缺阈值/缺版本,模型会倾向于"补全"。
- 部分可回答:能回答"上限",但回答不了"例外/审批",需要把回答粒度拆开管理。
- 引用不等于可靠:模型可以"随便引用一个段落"让回答看起来像有出处。
因此,这一节关心的是两件事:
- 证据是否真的相关/充分
- 答案的每个关键断言是否被证据支持(grounded)
3.【Reliable RAG】是通过几类什么设计,分别如何解决的问题
这一环节常见可以拆成 4 类设计(下面实例会逐个跑出来):
-
【设计 1:检索相关性过滤(relevance grading)】
- 怎么得到:对每个检索结果做一个"与问题是否相关"的判别(可以用 LLM 判别,也可以用 embedding 相似度阈值做快速筛)。
- 解决:把明显跑偏的证据先丢掉,避免噪声段落污染后续生成与检查。
-
【设计 2:答案 groundedness 检查(hallucination / support grading)】
- 怎么得到:给定"证据集合 + 生成答案",判断答案是否被证据支持(最小形态是 yes/no;更强的是定位不支持的断言)。
- 解决:发现"看起来合理但证据不支持"的回答,阻止它直接输出。
-
【设计 3:证据高亮(verbatim evidence highlights)】
- 怎么得到:从证据文档中抽出能够逐字匹配/直接支撑答案的片段(span),并把这些片段随回答一起输出或用于审计。
- 解决:把"引用"变成"可核对的证据片段",降低"伪引用"。
-
【设计 4:拒答 / 降级回答(refusal & partial answer)】
- 怎么得到:当相关性不足或 groundedness 未通过时,不输出完整答案;改为拒答,或只输出"证据支持的那部分",并明确缺口与下一步(例如需要更多信息/需要更换数据源)。
- 解决:把系统从"错而自信"变成"可控、可审计、可迭代"。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册)
- 知识库:《公司员工手册》差旅政策(住宿标准/例外情形/审批要求)
- 目标问题(多意图) :
- Q:"上海出差住酒店能报多少?哪些情况可以超标?超标需要谁审批?要准备什么材料?"
为了看清可靠性闸门的作用,我们故意跑 3 个回合:可回答 / 部分可回答 / 不可回答。
Turn 1:可回答型(证据齐全)------全链路通过
你在上游已经拿到一个"看起来不错"的 context(包含上限、例外、审批、材料四类证据)。
-
相关性过滤(设计 1)
- 你会把"差旅概述/文化宣导/与住宿无关的报销细则"这类段落过滤掉
- 最终留下的 docs 更集中在"住宿标准/例外/审批/材料"
-
生成答案(baseline 生成)
- 这里先不追求文采,只要把四个子意图回答完整
-
groundedness 检查(设计 2)
- 你会得到一个"通过"的信号:答案的关键断言都能在证据里找到支持
-
证据高亮(设计 3)
- 你会抽出几段"可逐字核对"的片段,例如:
- "一线城市上限 .../晚"
- "会议/旺季/统一订房 ... 可上浮至 ...(含审批条件)"
- "超标需 ... 审批;超过 ... 需 ... 审批"
- "报销材料:发票/订单/会议通知 ..."
- 你会抽出几段"可逐字核对"的片段,例如:
此时输出的答案会长成这样:回答 +(可选)高亮证据片段,用户能直接核对。
Turn 2:部分可回答型(证据缺口)------只输出支持的部分
我们把问题换成一个更"刁钻但常见"的问法:
- Q2:"如果旺季酒店涨价到 900/晚,公司允许报销吗?谁审批?"
假设你的知识库证据只覆盖到"上浮至 800/晚"的阈值,并没有"900/晚"的规则。
- 相关性过滤(设计 1):仍然能找到"旺季/会议/上浮阈值/审批"相关段落。
- 生成答案:模型很可能会"顺手推断"900/晚也可以(这是风险点)。
- groundedness 检查(设计 2) :会发现"900/晚允许报销"这一断言证据不支持。
- 拒答/降级(设计 4) :最终你应该输出:
- 证据支持的部分:手册只明确支持"在某些条件下可上浮至 800/晚,并需相应审批"
- 证据不支持的部分:没有"900/晚是否允许"的条款 → 不能给确定结论
- 下一步:建议用户提供更具体的制度条款/或将问题转给人工/或触发外部数据源
这就是 Reliable RAG 最重要的价值:把"看起来能答"变成"证据能支持才答"。
Turn 3:不可回答型(超出知识库范围)------明确拒答并解释原因
再换一个明显越界的问题:
- Q3:"上海出差的餐补每天多少?(以及是否能和住宿补贴叠加)"
如果你的知识库只索引了"住宿政策",没有"餐补政策":
- 相关性过滤(设计 1):检索结果要么很少,要么多为"差旅相关但不含餐补"的段落。
- groundedness 检查(设计 2):任何具体金额都无法被证据支持。
- 拒答(设计 4):输出"当前证据不足,无法回答餐补金额与叠加规则",并建议补充数据源或指向餐补章节/制度。
5.【Reliable RAG】总结
- 这一环节的核心不是让回答"更聪明",而是让它更可控、更可核对、更不瞎编。
- 你应带走的四个闸门:
- 相关性过滤:先把明显跑偏的证据扔掉
- groundedness 检查:答案不被证据支持就不让过
- 证据高亮:把"引用"变成"可核对片段"
- 拒答/降级:只说证据支持的部分,明确缺口与下一步
环节:Evaluation(评估闭环:指标定义 + 批量评测 + 端到端门槛)
1.【Evaluation】在 RAG 里的位置
评估不在离线索引或在线问答链路里"占一个插槽",它更像覆盖全链路的一层:你每做一次优化(切分、改写、融合、重排、扩窗、压缩、可靠性闸门......),都要能回答一句话:
它到底让系统变好了,还是只是换了一种看起来更像对的说法?
因此 Evaluation 的位置是:
- 上游:一套固定的测试集(问题、标准答案/判定规则、数据版本)
- 中游:对同一套问题跑不同配置/不同版本的 RAG,记录中间产物(检索、上下文、答案、引用)
- 下游:汇总成可对比的分数 + 失败样例 + 失败模式分布,用来驱动下一轮优化
2.【Evaluation】要解决 RAG 什么问题
没有评估闭环时,你会遇到这些"长期必翻车"的问题:
- 优化不可验证:你觉得 chunk/检索/压缩/拒答"更合理了",但不知道整体对用户是否更好。
- 维度互相打架:重排提升了 correctness,却降低了 faithfulness;压缩减少成本,却漏了关键条件。
- 回归不可见:今天改了 prompt/阈值,某类问题悄悄变差了,但你直到线上投诉才知道。
- 可靠性无法量化:你加了 groundedness 检查,但拒答率上升是不是"更可靠"还是"更无用"?
所以评估的目标不是"给一个总分",而是让你能稳定看清:
- 回答到底对不对(Correctness)
- 回答是否被证据支撑(Faithfulness / Groundedness)
- 证据是否真的有用(Retrieval / Context Relevance)
- 在证据不足时系统是否表现得合理(拒答/部分回答是否合格)
3.【Evaluation】是通过几类什么设计,分别如何解决的问题
评估闭环通常可以拆成 5 类设计(下面实例会逐个跑出来):
-
【设计 1:先把指标分清(Correctness / Faithfulness / Relevance)】
- 怎么得到 :
- Correctness:回答 vs 标准答案(需要 ground truth)
- Faithfulness / Groundedness:回答是否能从给定上下文推出(不一定需要 ground truth)
- Retrieval/Context relevance:检索/上下文对问题是否有用(可用平均相关度近似)
- 解决:避免"一个分数解释所有问题",并把优化定位到对应插槽。
- 怎么得到 :
-
【设计 2:构建"干净的测试集"(每类失败模式单独可测)】
- 怎么得到:把问题按类型拆开准备:事实型、综合型、条件/阈值型、不可回答型(并明确每类的判定规则)。
- 解决:不把"检索失败"与"生成瞎编"混在一起,让你能针对性迭代。
-
【设计 3:LLM-as-judge 的可复用指标函数】
- 怎么得到:用一个稳定的 judge 模型,把每个维度封装成可复用评测器(输出 0~1 或 yes/no,并附带简短理由)。
- 解决:让离线批量评测可自动化,不必每次人工逐条看。
-
【设计 4:把评测跑成"批处理"(框架化跑分 + 保存中间产物)】
- 怎么得到:用评测框架把样本批量跑完,输出聚合统计与样例明细(例如 DeepEval 的 correctness/faithfulness/contextual relevancy;或 Open-RAG-Eval 读取 CSV 批量评测)。
- 解决:形成可重复、可对比、可回归的"评测作业"。
-
【设计 5:端到端门槛(pass/fail)与回归标准】
- 怎么得到:为关键指标设置阈值(例如 faithfulness ≥ 0.7,拒答率 ≤ 某区间,且不可回答型必须拒答),并把它变成发布门槛。
- 解决:把评估从"看报告"变成"能拦住坏版本上线"。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册)
我们把"员工手册差旅政策"这套知识库固定住,然后准备一份小评测集,用来对比不同配置。
Turn 1:做一份最小评测集(设计 2)
你准备 6 个问题(示意),并给出对应的判定规则:
- 事实型(有标准答案)
- Q1:住宿上限是多少?(需要返回正确金额/条件)
- Q2:超标审批到哪个角色?(需要返回正确审批链路/阈值)
- 综合型(覆盖多个证据)
- Q3:上限 + 例外 + 审批 + 材料(需要覆盖四块要点)
- Q4:会议统一订房导致超标怎么处理?(需要命中触发条件 + 处理方式)
- 条件/阈值型(容易被"补全")
- Q5:旺季涨到 900/晚能否报销?(如果手册无 900 条款,标准应为"无法从证据确定/只说明 800 的规则")
- 不可回答型(必须拒答)
- Q6:餐补每天多少?(如果知识库没有餐补条款,必须拒答)
你会发现:这份小集就足够覆盖我们前面讲过的大多数失败模式(缺条件、碎片命中、瞎补全、该拒不拒)。
Turn 2:先把三个核心指标跑起来(设计 1 + 3)
你用 judge 模型实现三个可复用评测器(不用追求完美,先可跑、可复用):
- Correctness(Q1Q4):01
- Faithfulness(Q1~Q5):0/1 或 0~1(只看"是否被上下文支持")
- Retrieval relevance(Q1Q6):01(看检索/上下文是否真的围绕问题)
这一步跑出来的价值是:你马上能区分开两类问题:
- "检索/上下文就错了" → relevance 低
- "上下文对,但答案乱说" → faithfulness 低
Turn 3:对比两个配置(把提升跑出来)
你至少跑两个配置对比:
- 配置 A(baseline):简单 top-k + 直接拼接 + 不做可靠性闸门
- 配置 B(优化):fusion/rerank + 扩窗/RSE + compression(以及更干净的 context building)
你会看到典型变化:
- B 的 relevance 往往更稳(证据更"对题")
- B 的 correctness 往往更高(综合题覆盖更全)
- 但 B 的 faithfulness 不一定自动变好:如果生成阶段仍会"补全",它依然可能在 Q5 上翻车
这会自然引出:仅靠检索与上下文优化,不足以保障可靠性,需要 Reliable RAG 的闸门配合。
Turn 4:把"可靠性闸门"纳入评测(设计 5)
你把配置 C 加进来:
- 配置 C:在 B 的基础上,加上 relevance filter + groundedness check + refusal/partial answer
然后你重点观察两件事:
- Q5(900/晚):C 能否从"瞎答"变成"只回答证据支持的 800 规则,并明确缺口"
- Q6(餐补):C 是否稳定拒答
此时,评估不只看 correctness/faitfulness,还要看:
- 拒答率(拒得是否"该拒才拒")
- 不可回答题通过率(必须拒答才算通过)
Turn 5:把评测跑成"批处理作业"(设计 4)
当你把"每条样本需要记录的中间产物"固定下来(query、检索 passages、最终 context、生成答案、引用/高亮),你就可以把结果整理成一种可批量评测的结构:
- 一条样本 =
question + retrieved_passages + generated_answer (+ citations)
然后用框架把它批量跑完,输出:
- 聚合指标(均值/分位数/通过率)
- 明细样本(哪条失败、失败理由是什么)
这样你就得到一个可重复运行的"评测作业":每次改动 pipeline,跑一遍就知道哪里变好/变坏。
5.【Evaluation】总结
- 评估闭环的本质是:把"优化感觉"变成"可对比证据"。
- 你最该先跑起来的三件事:
- 指标拆分:correctness / faithfulness / relevance
- 小而干净的测试集:事实/综合/条件/不可答
- 批处理与回归门槛:能一键复跑、能拦坏版本
环节:Iterative / Adaptive Retrieval(迭代检索与策略路由:会"纠错"的检索)
1.【迭代检索与策略路由】在 RAG 里的位置
这一环节发生在 在线问答阶段 ,主要落在 Query Transformation ↔ Retrieve/Fuse/Rerank 之间:它把"一次检索"升级成"可迭代的检索过程",并且让系统能根据问题类型选择不同的检索策略。
- 上游:用户问题(以及可选的用户上下文/历史对话/历史反馈)
- 中游:问题分类/路由 → 选择检索策略 →(必要时)再改写/再检索 → 输出最终证据
- 下游:Context Building / Reliable RAG / Generate
一句话:当一次检索不够时,这一环节决定"要不要再跑一轮、下一轮怎么跑、跑到什么时候停"。
2.【迭代检索与策略路由】要解决 RAG 什么问题
即使你已经有了融合/重排/扩窗/压缩,现实里仍会遇到这些"必须多跑一步"的情况:
- 同一主题不同问法导致波动:一句"能不能报销""怎么处理"太口语,检索命中不稳定。
- 一次 top-k 无法覆盖多意图:上限/例外/审批/材料混在一句话里,一次检索很容易只满足其中一块。
- 问题类型不同,最优策略不同 :
- 数字/阈值型更需要精确命中与精排
- 总结/分析型更需要覆盖面与去重复
- 结合用户背景的上下文型需要把背景注入检索或排序
- 系统"不记错/不记好":用户刚说"这个不相关/这个很有用",下一次系统仍然可能重复犯错。
所以这一节关心的是:把"检索不佳"变成一个可观测信号,然后用下一步行动把它拉回可用区间。
3.【迭代检索与策略路由】是通过几类什么设计,分别如何解决的问题
这类系统通常由 5 类设计拼出来(后面实例会按顺序跑出来):
-
【设计 1:把反馈变成可复用资产(Feedback Memory)】
- 怎么得到:把每次问答的反馈记录下来(例如 relevance/quality 1-5、失败原因、用户更正),形成一条条可追加的记录。
- 解决:让系统"记住什么问法/什么证据/什么回答是好/坏的",避免反复踩坑。
-
【设计 2:用反馈驱动 Query 改写 + 轻量重排(Feedback-aware Retrieval)】
- 怎么得到:先从反馈记忆里找与当前问题相似的高质量片段 → 让模型生成更适合检索的改写 query(并给出少量 focus terms)→ 拉取较大的候选集(fetch-k)→ 用 focus terms 做轻量重排/去噪 → 输出最终 top-k。
- 解决:稳定口语问法下的召回,并把"更像答案的证据"推到前面。
-
【设计 3:把"高质量问答"写回索引(Incremental Write-back)】
- 怎么得到:定期把高质量反馈里的 Q/A(或被证据支持的摘要)写回索引(作为新增可检索条目/辅助索引)。
- 解决:让知识库随着真实使用逐步"长出更好检索的表述",提升后续召回稳定性。
-
【设计 4:问题分类与策略路由(Adaptive Retrieval Router)】
- 怎么得到:用模型把问题分类成几类(例如事实型/分析型/观点型/上下文型),并输出简短理由(用于调试与审计),然后按类型选择不同检索策略。
- 解决:避免"一招走天下",让检索策略贴合问题结构。
-
【设计 5:预算与停止条件(Budget + Stop Conditions)】
- 怎么得到:设置最大迭代轮数、每轮 fetch-k、以及"何时需要再跑一轮"的触发条件(例如相关性太低、覆盖不足、Reliable RAG 判定证据不支持)。
- 解决:控制成本/延迟,避免系统陷入无休止的"再试一次"。
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册)
- 知识库:《公司员工手册》差旅政策(住宿标准/例外情形/审批要求)
- 问题(口语 + 多意图) :
- Q:"上海出差住酒店能报多少?超了怎么办?要找谁批?需要什么材料?"
为了让"迭代/路由"在例子里跑出来,我们刻意加入两类真实信号:
- 覆盖不足信号:答案漏了"例外条款"或"审批阈值"
- 不支持信号:出现"900/晚也能报"这种证据不支持的推断
Turn 1:把用户反馈记下来(设计 1)
你先用一次常规 RAG 跑 Q,输出一个 baseline 答案。用户反馈:
- "你只回答了上限,没说例外和审批;而且材料也没写全。"
此时你记录一条反馈(示意字段):
question: Qrelevance: 4(主题相关)quality: 2(覆盖不全)note: "漏例外/漏审批阈值/漏材料"
这个动作看似简单,但它改变了系统性质:下一次系统不再是"从零开始检索",而是带着可复用的历史线索。
Turn 2:用反馈驱动改写 + 拉大候选 + 轻量重排(设计 2)
你再次收到类似问法(或同一个用户换个说法):
- Q':"我去上海开会住酒店,报销标准怎么走?超标咋办?"
怎么跑:
- 从反馈记忆里找到与 Q' 相似的高质量片段(例如之前关于"住宿标准/例外/审批/材料"的反馈与摘要)
- 让模型输出一个更适合检索的改写 query,并给出
focus_terms(例如:住宿标准/报销上限/会议/例外/超标/审批/阈值/材料) - 用改写后的 query 先取 较大的候选集(例如 fetch-k=20)
- 用
focus_terms做一次轻量重排:包含更多焦点词的段落排前,把"差旅概述"类段落压下去 - 输出最终 top-k(例如 k=6)交给后续 Context Building
你会看到的变化:
- top-k 更稳定地覆盖到"标准 + 例外 + 审批 + 材料"四块证据
- 同时减少"同主题但不回答"的概述段落占位
Turn 3:把高质量问答写回索引(设计 3)
当某些问法反复出现(例如"超标怎么办/谁审批/材料有哪些"),你会积累到一批高质量记录(relevance≥4 且 quality≥4)。
怎么跑:
- 把这些高质量记录整理成"可检索条目"(例如
Q:... A:...(含引用锚点/条款号)或 "条款要点摘要") - 写回到一个增量索引里(可以理解为一个"调优后的索引层")
你会看到的变化:
- 同样的口语问法再次出现时,检索更容易命中这些"更像用户问法"的条目
- 在不改原始手册的前提下,系统逐步长出更强的"问答对齐能力"
Turn 4:按问题类型自动选策略(设计 4)
我们把同一主题下的不同问题拆成 4 个变体,让路由机制跑出来:
- 事实/阈值型 :Qf:"住宿上限多少?超标到 800/晚需要谁批?"
- 典型策略:更强调"精确命中 + 精排"(改写 + fetch-k 更大 + 选 top-k)
- 分析/总结型 :Qa:"差旅住宿报销这块有哪些约束?最容易踩坑的点是什么?"
- 典型策略:拆子问题覆盖面 + 去重复(多子查询检索 → 汇总候选 → 选覆盖面更好的 top-k)
- 上下文型 :Qc:"我经常去上海开会,能给我一个更省事的报销建议吗?"
- 典型策略:把用户上下文注入 query/排序(例如优先检索"会议/统一订房/审批材料")
- 观点型(当知识库里包含 FAQ/讨论记录时) :Qo:"这个差旅政策有哪些常见争议点?"
- 典型策略:生成多个视角(员工/财务/管理者)→ 按视角检索 → 选代表性片段
你会看到:同一个知识库,不同问题会触发不同"检索动作序列",从而让证据集更贴合问题结构。
Turn 5:加入预算与停止条件,避免"无限再试一次"(设计 5)
你设置一个最小可用的控制面:
max_iters=2(最多两轮检索)fetch_k第一轮 20、第二轮 40(第二轮更"用力")- 触发第二轮的条件(任一满足即可):
- 证据覆盖不足(缺例外/缺审批/缺材料中的某块)
- Reliable RAG 判定 groundedness 不通过(答案出现证据不支持的断言)
- relevance 太低(明显跑偏)
你会看到的结果:
- 系统会在"确实需要再跑一轮"的时候再跑
- 并且能在第二轮失败时及时停下,转为拒答/澄清/请求补充信息
5.【迭代检索与策略路由】总结
- 这一环节的目标是把 RAG 从"一次性管道"升级成"可自我修正的过程"。
- 你应带走的核心组合拳:
- 反馈记忆 → 让系统不再从零开始
- 反馈驱动改写 + 拉大候选 + 轻量重排 → 稳定召回与覆盖
- 写回索引 → 让知识库随着真实使用变得更"问答友好"
- 分类路由 → 不同问题走不同检索动作序列
- 预算与停止 → 控成本、控延迟、控行为可预期
环节:Explainable Retrieval(可解释检索:不仅返回证据,还解释"为什么是它")
1.【可解释检索】在 RAG 里的位置
这一环节发生在 检索之后、重排/上下文拼装之前(也可以作为检索的一部分一起封装):它对每条候选证据补上一层"可读解释",让你能看见"这段证据到底因为什么被选中"。
- 上游:Retrieve / Fusion / Rerank 输出的候选
Document[](可带 score) - 中游:为每条候选生成解释信号(本节)
- 下游:
- 调试/可观测:定位问题到底出在 query、embedding、索引、还是重排
- 产品体验:向用户展示"为什么引用这段"
- 训练后续环节:为 feedback loop / 评测提供更可解释的中间产物
一句话:可解释检索不是为了换掉检索算法,而是为了让"检索依据可见、可调、可审计"。
2.【可解释检索】要解决 RAG 什么问题
当你的系统变复杂(融合/重排/扩窗/压缩/迭代/路由都上了),你最容易遇到的不是"不会做",而是:
- 不知道为什么命中这段:top-k 看起来"差不多相关",但答案却偏了。
- 不知道问题出在哪一层:是 query 写法不好?embedding 不合适?索引里有噪声?还是 rerank 把对的证据排下去了?
- 分数不可读:score/距离对人没有意义,更难用来解释给业务方或用户。
- 需要可审计:你想证明"回答确实来源于证据",而不是"看起来像引用"。
因此,这一节要把"检索黑箱"拆开,给你两类解释信号:
- 硬信号:检索返回的 score/距离/相似度、rank、metadata
- 软信号:把"为什么相关"说清楚的可读解释(并给出可核对的关联锚点)
3.【可解释检索】是通过几类什么设计,分别如何解决的问题
可解释检索最常见的实现可以拆成 5 类设计(下面实例会按顺序跑出来):
-
【设计 1:把检索硬信号暴露出来(rank/score/metadata)】
- 怎么得到 :让 retriever 返回
(doc, score),并保留 doc 的source/section/page/span等 metadata。 - 解决:至少让你能看见"它是第几名、分数大概差多少、来自哪里"。
- 怎么得到 :让 retriever 返回
-
【设计 2:生成可验证的关联锚点(anchors)】
- 怎么得到:抽出"问题与证据的共同锚点",最小可以是词面重叠/实体/数字/条款号;更强可以是概念短语(由模型输出)。
- 解决:避免解释变成空话,让你能快速核对"相关点到底在哪"。
-
【设计 3:LLM 解释器(rationale + relevant 判别)】
- 怎么得到 :对每条候选证据,用 LLM 输出:
relevant: 这段是否真的可能用得上(粗粒度过滤信号)rationale: 2-4 句解释相关性(主题/定义/因果/条件-结论等)anchors: 若干可核对锚点
- 关键约束:解释器的任务是"解释相关性",不是"回答问题",并且要忽略证据中的指令性文本(防提示注入)。
- 解决:把"检索依据"变成可读、可调试的文字。
- 怎么得到 :对每条候选证据,用 LLM 输出:
-
【设计 4:用解释信号反哺检索(过滤/轻量重排/路由)】
- 怎么得到 :
- 过滤:把
relevant=false的候选丢掉 - 轻量重排:优先保留 anchors 命中更强的候选
- 路由:当解释显示"只擦边/缺关键锚点",触发 query 改写或第二轮检索
- 过滤:把
- 解决:让解释不止是"看",还能"用来纠错"。
- 怎么得到 :
-
【设计 5:把解释写进可观测记录(trace/评测样本)】
- 怎么得到 :把每次检索的
query → candidates → score → explanation记录下来,作为失败复盘与评测样本的一部分。 - 解决:让你能在"为什么这版变差了"的问题上快速定位到具体证据与理由。
- 怎么得到 :把每次检索的
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册)
- 知识库:《公司员工手册》差旅政策(住宿标准/例外情形/审批要求)
- 问题 :
- Q:"上海出差住酒店能报多少?哪些情况可以超标?超标需要谁审批?要准备什么材料?"
我们假设检索阶段已经返回了 5 条候选(其中混入两类"看起来相关但不回答"的段落):
- D1:
住宿标准(含城市等级与上限)(很可能真相关) - D2:
差旅政策总原则/目的(主题相关,但不回答阈值/审批) - D3:
例外情形(触发条件 + 处理方式)(真相关) - D4:
审批要求(阈值 + 角色)(真相关) - D5:
一般报销流程(非差旅住宿专属)(擦边)
Turn 1:先把硬信号展开(设计 1)
你把每条候选都展开成"可读的一行":
rank/score(注意:不同后端 score 语义可能不同,有的越大越相似,有的越小越相似)source(来自哪份手册/哪一章/哪一条款)excerpt(截取 200~300 字,方便扫一眼)
此时你至少能回答:系统把哪些东西当成"相似",以及它们之间分数差距大不大。
Turn 2:补锚点,让相关性"可核对"(设计 2)
你为每条候选生成 anchors(最小可行做法是词面/实体/数字锚点),例如:
- D1 anchors:
上海、住宿、上限、600/晚、城市等级 - D3 anchors:
例外、会议、旺季、统一订房、上浮至 800 - D4 anchors:
超标、审批、主管、总监、阈值 - D2 anchors:可能只有
差旅、政策(缺少阈值/审批锚点) - D5 anchors:
报销、发票(但缺少"差旅住宿"专属锚点)
你会看到:D2/D5 的锚点很弱,属于"主题相关但不回答"的高风险段落。
Turn 3:让解释器把"为什么相关/不相关"讲清楚(设计 3)
你对每条候选跑一次解释器,得到三件东西:
relevant: yes/norationale: 2-4 句(例如 D2 会被指出"只讲原则,不包含上限/例外/审批细则")anchors: 解释器认为的关键关联点(与上一轮 anchors 互相校验)
你会得到一个很关键的可观测结果:候选里哪些是"能回答"的,哪些只是"擦边"。
Turn 4:把解释信号用回去(设计 4)
你做两件最小动作:
- 过滤 :把
relevant=false的候选去掉(例如 D2 或 D5) - 轻量重排:优先把 anchors 覆盖"上限/例外/审批/材料"四块的候选放前面
你会看到的变化是:
最终证据集合更"对题",Context Building 阶段更容易拼出覆盖完整的上下文包。
Turn 5:把解释写进记录,用于复盘与评测(设计 5)
当某次线上出现"答偏了",你不再只能看"最终答案",而是能回看:
- 当时的 query 是什么
- 候选里混进了哪些擦边段
- 解释器为什么认为它相关/不相关
- 最终上下文为什么会缺某块锚点(例如缺审批阈值)
这会让调参从"玄学"变成"有抓手的工程迭代"。
5.【可解释检索】总结
- 可解释检索的核心产出不是"更好的答案",而是"更清楚的中间产物":你能看见检索为什么这么做。
- 你应带走的最小组合:
- 硬信号 (rank/score/metadata)+ 锚点 (anchors)+ 可读解释(rationale)
- 解释不仅能展示,还能用于过滤/重排/触发第二轮检索
环节:高级架构(GraphRAG / RAPTOR / MemoRAG / Self-RAG / CRAG / Agentic RAG)
1.【高级架构】在 RAG 里的位置
高级架构仍然发生在 RAG 的主链路上,但它不再只是"把某个插槽调好一点",而是引入更强的中间层/控制层,来应对你在基础优化都做完后仍然会反复遇到的难题(多跳、长文、不确定、交付型多步骤)。
把它放回到全链路里看,大致是这几类位置:
- GraphRAG :主要发生在 Retrieve,通过"图结构中间层"把连接证据链补齐,再把图上结果映射回可引用 passages
- RAPTOR / MemoRAG :主要发生在 离线索引 ↔ 在线检索之间,先把"可检索的中间产物"做强(摘要树/记忆),在线再下钻/再检索
- Self-RAG / CRAG :主要发生在 在线问答阶段,把"评估与纠错"变成流程的一部分(关卡质检/检索质量分流)
- Agentic RAG :主要发生在 在线问答阶段,把检索/重排/核验封装成工具,让系统能编排多步骤完成交付
2.【高级架构】要解决 RAG 什么问题
当你已经把 chunk、query 改写、融合检索、重排、Context Building、可靠性闸门、评估闭环都做了,仍然会遇到几类"靠调参很难根治"的失败模式:
- 多跳与桥梁缺失:top-k 命中结论段,却漏触发条件/中间关系段,证据链断裂。
- 长文上限:只命中概述或只命中局部细则,缺"全局结构 → 局部细则"的导航能力。
- 覆盖不全与不确定:同一问题会在可答/部分可答/不可答之间切换,需要系统自我判定并选择下一步。
- 交付型多步骤:一次问答需要多次检索、重排、核验,甚至外部数据源;固定链路会越来越臃肿、越来越难维护。
因此高级架构的目标不是"让某一次回答更像人",而是让系统具备更强的 组织能力:能补链、能下钻、能自检、能走纠错路径、能把多动作编排成稳定产出。
3.【高级架构】是通过几类什么设计,分别如何解决的问题
把这几种高级架构按"引入了什么中间层/控制层"归纳为 6 类设计(后面实例会逐个跑出来):
-
【设计 1:GraphRAG(图扩展补连接)】
- 怎么得到 :离线把语料构成图(chunk 图 / 实体-关系图 / 社区摘要等);在线先定位起点(向量/实体/社区)→ 在图上扩展补桥梁 → map-back 到原文 passages(带 source/section/span)。
- 解决:多跳问题里最常见的"连接段缺失/中间关系丢失"。
-
【设计 2:RAPTOR(摘要树下钻)】
- 怎么得到:离线把基础单元向量化→聚类成簇→每簇生成摘要节点→再对摘要节点聚类/摘要,形成多层树。在线先在概括层命中主题,再沿子树下钻检索细则。
- 解决:长文场景下"只命中概述/只命中局部"的不稳定。
-
【设计 3:MemoRAG(记忆先行 + surrogate queries)】
- 怎么得到:离线把 chunk 抽成 key-value 记忆并建记忆库;在线先从记忆里取线索,再生成 surrogate queries 批量检索原文,再汇总去重。
- 解决:跨章节问题的"检索线索不对齐/召回不稳"。
-
【设计 4:Self-RAG(逐关卡质检 + 选择)】
- 怎么得到:把一次问答拆成结构化关卡(是否检索→证据相关→候选生成→支持度→效用→选择),每一步输出可编程信号(yes/no、supported/unsupported...)。
- 解决:用错证据、证据不支持、以及"明明不该答却硬答"。
-
【设计 5:CRAG(检索质量分流 + 外部纠错)】
- 怎么得到:对本地检索结果打相关性/可用性分数,按阈值走三路:高相关→本地;低相关→外部数据源;中间→本地+外部融合(并可压缩外部噪声)。
- 解决:本地覆盖不全或过期时的"假装知道"。
-
【设计 6:Agentic RAG(工具编排)】
- 怎么得到 :把
retrieve、rerank、grounded_check、highlight_evidence、evaluate等封装成 tools;模型按任务动态决定是否调用、调用几次、如何组合。 - 解决:交付型问题的多步骤组织(把复杂流程从写死链路变成可组合动作)。
- 怎么得到 :把
4.【实例】通过一个特定例子完整覆盖展示每个设计在实例中具体是如何工作的
例子(沿用员工手册,但把场景升级成"长文 + 多章节 + 覆盖不全")
假设你的知识库是一份更长的《员工手册》,包含:
- 差旅(住宿/交通/餐补/审批/材料)
- 报销流程(通用规则、票据要求、税务要求)
- 例外政策(会议/旺季/统一订房、特殊岗位补贴)
- 版本变更记录(不同月份生效差异)
我们用同一个主题贯穿多轮,让高级架构的关键动作都"跑出来"。
Turn 1:先跑一次"只用 top-k"的多跳问题(对照)
问题:
- Q:"会议统一订房导致住宿超标时,允许报销到多少?需要谁审批?要准备哪些材料?如果超过 800/晚 又怎样?"
常见现象是:检索命中了"上浮到 800/晚"的结论段,却漏了触发条件;或者命中了审批链路,却漏了阈值与例外条件。结果就是回答把条件套错、或回答不完整。
Turn 2:GraphRAG 在图上扩展补连接(设计 1)
怎么跑(关键动作):
- 先定位起点(例外段/审批段/阈值段任意命中都可以当 seed)
- 在图上扩展,把"触发条件 → 阈值 → 审批 → 材料"的桥梁证据补齐
- 把图上节点/关系 map-back 成可引用 passages,再进入 Context Building + Reliable RAG
你会看到的变化:证据集更像一条连续的"规则链",而不是几段互不相干的片段。
Turn 3:RAPTOR 摘要树"先概括后细则"(设计 2)
问题:
- Q1:"差旅政策里,住宿和餐补分别有哪些硬阈值?例外条款有哪些?审批链路怎么走?"
怎么跑:
- 先在摘要树高层节点检索(差旅总体/阈值摘要/审批摘要)
- 对命中的摘要节点下钻,只在对应子树里找细则条款
- 把"硬阈值/例外/审批"三类条款拼成 context
你会看到的变化:覆盖更全、漏检更少;系统行为更像"先看目录/概览,再翻细则"。
Turn 4:MemoRAG 先查记忆再批量检索原文(设计 3)
问题:
- Q2:"会议统一订房导致超标时,需要哪些材料?以及餐补是否受影响?"
怎么跑:
- 先查记忆命中
统一订房、超标材料、餐补规则等 topic - 生成 surrogate queries(围绕材料清单、餐补影响、审批条件分别发散)
- 批量检索原文 → 汇总去重 → 进入 Context Building
你会看到的变化:比起直接拿 Q2 去检索,更稳定地命中跨章节关键句。
Turn 5:Self-RAG 把"可答/不可答/部分可答"做成关卡(设计 4)
问题:
- Q3:"旺季涨到 900/晚能不能报销?如果不能,最高到多少?谁审批?"
怎么跑(关键关卡):
- 检索决策:阈值类必须检索
- 支持度检查:发现"900/晚允许报销"缺证据支持
- 效用选择:输出"证据支持的部分(例如 800 规则)+ 明确缺口",或拒答并解释缺证据
Turn 6:CRAG 用检索质量决定是否走外部纠错(设计 5)
问题(刻意让本地覆盖不全):
- Q4:"我们公司今年(2026)上海餐补最新标准是多少?"
怎么跑:
- 先做本地检索 → 对结果做相关性/可用性打分(例如发现条款明显过期或缺失)
- 触发分流:低相关走外部数据源;中间走本地+外部融合;高相关只用本地
- 把外部证据压缩成可核对片段,再进入 groundedness 检查与证据高亮
你会看到的变化:系统不会用旧条款冒充最新标准;纠错路径可控、可审计。
Turn 7:Agentic RAG 工具编排完成"速查交付"(设计 6)
问题:
- Q5:"请给我一份'上海出差报销速查':住宿上限/例外/审批/材料/餐补;如果某项没有证据请标注出来。"
你会看到的工具编排:
- 多次
retrieve(按小节分别检索:住宿/例外/审批/材料/餐补) rerank(每类选到最能回答的 top-n)grounded_check(逐小节检查支持度)highlight_evidence(逐小节抽可核对片段)- 汇总输出(缺口显式标注)
5.【高级架构】总结
- 高级架构的共同点:引入更强的中间层/控制层,让系统能 补链、下钻、自检、分流纠错、编排多步骤。
- GraphRAG 解决多跳连接证据链;RAPTOR/MemoRAG 解决长文与跨章节召回稳定性;Self-RAG/CRAG 解决不确定与纠错路径;Agentic RAG 解决交付型多步骤组织。
- 如果你继续深化这一节,最有效的写法是:把每个架构都落到"它新增了什么中间产物/信号""它如何把结果映射回可引用证据""它如何被评估与监控"这三件事上。