RAG 的工程现实
专栏:Agent 工程 · 第 10 / 18 篇上一篇的 MiniRAG 在你的 10 个测试里大概命中了一半——这是正常的。RAG 的”最后一公里”全在工程细节里。这篇讲五个决策点,最后给一张总决策表。
:::info 学习目标 完成本篇后你能够:为语料选择分块策略;实现关键词+向量混合检索与 LLM 重排;搭建 20 条黄金问答集并量化每次改动。 前置:第 9 篇的 MiniRAG 可用。预计时长:90 分钟。 :::
:::note 本章术语速查(新手建议先读)
- 混合检索:向量检索(懂语义)+ 关键词检索(懂专有名词)两路一起上,结果合并。
- BM25:经典的关键词检索算法,专有名词匹配比向量靠谱。
- RRF(倒数融合):把多路检索结果合并排序的公式——每路按名次给分,累加。
- 重排(Rerank):先用粗检索召回 20 条,再用更精确的模型挑出最好的 4 条。
- 黄金集(Golden Set):人工整理的”问题 + 正确答案出处”测试集,用来量化 RAG 的命中率。
- 拒答:检索不到可靠依据时,明确回答”不知道”而不是编造。 :::
决策一:分块——不是切得越碎越好
MiniRAG 按固定长度滑窗切,问题明显:一个完整的流程步骤被拦腰切断,检索到也读不懂。改进按语料形态选择:
- 结构化 Markdown:按标题层级切(
##为界),块内保留标题路径作前缀(“报销流程 > 差旅报销:”)——上下文跟着块走; - 代码:按符号切(函数/类为界)——不过 coding agent 通常直接用 grep,见第 9 篇;
- 通用文本:滑窗 + overlap,但块尺寸从「答案可能多长」反推,而非拍脑袋 500。
决策二:混合检索——关键词与向量的联姻
纯向量检索的弱点是专有名词:模型名、错误码、内部黑话,embedding 常常分不清。工程标配是混合检索:向量召回(语义相似)+ BM25 关键词召回(精确命中)+ 倒数融合(RRF)合并排序。dsh 的 session-query 就是这个思路的活例子——SQLite 全文检索(BM25 系)作为会话语料的检索底座。给自己的 MiniRAG 加关键词通道,往往比换 embedding 模型收益更大。
决策二补充:RRF 融合的最小实现
def rrf(rankings, k=60):
# 多路召回的倒数融合:每路按名次给 1/(k+名次+1) 分,累加
scores = {}
for ranking in rankings:
for rank, doc_id in enumerate(ranking):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
return dict(sorted(scores.items(), key=lambda x: -x[1]))
# 调用:rrf([向量召回top20, 关键词召回top20]) → 融合排序取前 N
k=60 是论文经验值:它让”任何一路的第一名”都无法碾压”两路的第二名”——融合的意义正在于此。
决策三:重排——召回宽、入库严
向量召回的 top-k 里经常一半是噪音。标准两段式:先宽召回(top-20,快、粗糙),再精排(用交叉编码器或直接让 LLM 给每条打相关性分,取前 4)。用 LLM 重排的最小实现就是把候选块和问题一起发给模型:“对回答这个问题,以下片段各自相关吗?返回相关的编号”。成本略高,命中质量提升立竿见影。
决策四:评估——没有评测集的 RAG 是玄学
延续第 13 篇先剧透的原则:给 RAG 建 20 条「问题 → 应命中的出处」的黄金集,每次改分块/换模型/调参数跑一遍命中率。两个解剖对象的日志设计在这里再次显价值:Codex 的 rollout 与 dsh 的 session 日志都完整记录了检索调用与引用出处——线上 agent 的真实未命中案例,就是你评测集的持续供给。
决策五:出处与拒答
检索结果必须带出处(文件 + 位置)进提示词,并明确指示模型:“引用片段作答;片段不足时明确说不知道,不要编造”。出处让用户可验证,拒答指令抑制幻觉——这一对组合是 RAG 产品可信度的底线。
检索质量的四个决策点串起来
总决策表:接知识的四种方式
总决策表:接知识的四种方式
| 手段 | 适用 | 不适用 | 代表 |
|---|---|---|---|
| 工具化探索(grep/read) | 结构化语料(代码库、文件树) | 无文件形态的海量文本 | Codex、dsh 的默认路径 |
| RAG | 无结构海量文本、需要出处 | 语料小到能塞进窗口 | 本篇 |
| 长上下文直塞 | 语料 < 数十页且高频使用 | 成本与延迟随规模爆炸 | Anthropic 长上下文 |
| 微调 | 固定的格式/风格/领域行为 | 事实性知识(会过时) | 领域专精 agent |
优先级从上到下试:能用工具就不上 RAG,能 RAG 就不微调。第 8 篇的 sub-agent 隔离常常是”知识太多”的更便宜答案。
随堂练习(带验收标准)
- 黄金集:把第 9 篇的 10 个测试升级成 20 条「问题 → 应命中出处」的黄金集,写一个命中率脚本。验收:
python rag_eval.py输出单个 0~100% 的数字; - 混合检索:加关键词通道(裸关键词计数即可)+ RRF 合并,重跑黄金集。验收:命中率提升可量化,专有名词类问题的改善最明显;
- LLM 重排:宽召回 top-20 → 模型打分 → 取前 4。验收:对比重排前后的命中率与每次问答成本,算出”每提升 1% 命中率花了多少额外 token”;
- 给
search_knowledge的工具描述补一条拒答指引,统计”不知道就说不知道”的比例变化。