RAG 不是技术问题,是工程方法论问题
这页不教你从零入门,而是回答”为什么 Demo 跑通了系统还是不好用”。重点是评估、badcase、实验设计、边界判断和项目落地顺序。
标签:评估优先 | Golden Dataset | 实验记录 | 方案边界
这页负责项目落地、评估和边界判断,不负责概念入门。
Page Summary
- 这页解决什么:把”能跑 Demo”升级成”能评估、能迭代、能讲边界”的工程化方法。
- 必须记住的结论:没有黄金数据集和指标,就没有有效优化;没有边界判断,就没有可信方案。
- 读完后的动作:先整理 20-30 条真实 badcase,再建立 Golden Dataset 和实验记录表。
01 五步工程方法论
先有标准,再有系统,再有优化
核心原则: 不要在没有评估标准的情况下开始构建系统。“感觉还不错”不是工程结论。黄金数据集要在写第一行检索代码之前就存在。
步骤 0 · 定义 MVP 边界(先于一切)
不要盲目开始写代码。三个核心问题必须先回答清楚,否则你在为一个模糊的目标优化。
- 用户是谁? → 内部员工 / 外部客户 / 特定角色(如销售、客服)
- 具体用例? → 一个用例,不是三个。“企业知识问答”太宽,“销售合同条款查询”才对。
- 数据源清单? → 1~2 个高质量数据源,不要上来就接十个系统。
- 成功标准? → 6 周内,用什么指标判断系统”可用”?先写下来。
⚠️ 避免过度扩张:每增加一个数据源,系统复杂度非线性增加。
步骤 1 · 构建黄金数据集(在建系统前)
这是整个项目的”尺子”。没有它,后续一切优化都是直觉驱动,而不是数据驱动。
- 来源优先级: 真实用户 query(最好)> 手工标注 > LLM 合成(最快但质量最低)
- 最小规模: 20 条可以起步,50~100 条才有统计意义
- 覆盖维度: 难度(简单/中等/困难)× 类型(事实性/概念性/流程性)
- 必须做: 8:2 拆分为开发集和测试集。测试集封存,不参与任何调参。
⚠️ 用测试集调参 = 在为特定数据集过拟合 = 指标虚高 = 上生产后打脸。
步骤 2 · 构建初始检索系统 + 量化评估
用最简单的方法建立基线,然后立刻量化。不要在没有基线数字的情况下开始优化。
- 起点: 向量检索(Dense)作为基线,不要上来就上混合检索
- 核心指标: Recall@K(有没有找到)/ MRR(找到的排在第几位)
- 分块策略: 先用固定大小+overlap(200~500字,10%~20%重叠),记录基线分数
- Embedding: 先用 text-embedding-3-small,有瓶颈再换
✓ 基线分数是后续所有优化的参照点。“比基线高”才是有效优化。
步骤 3 · 构建回复系统 + 手动错误分析
先接 LLM 生成回答,然后手动读 30~100 条失败案例。这一步不能跳过。
- 为什么要手动读? 自动化评估需要你先知道”要检查什么”。手动读是发现失败模式的唯一方法。
- 记录格式: query → 检索到的 chunks → 最终回答 → 失败类型 → 根因
- 自动化时机: 找到规律后,用关键词检查或 LLM-as-judge 自动化高频失败模式的检测
步骤 4 · 运行受控实验 + 迭代
每次只改一个变量。改了两个变量,你不知道是哪个起作用的。
- 实验优先级: 先优化检索(数据质量、分块),再优化生成(Prompt)
- 为什么检索先于生成? 检索决定天花板,Prompt 只能在这个天花板内发挥。
- 何时进入生产? 开发集指标稳定后,用测试集做最终评估。测试集只用一次。
步骤 ∞ · 生产监控 + 持续迭代
上线不是终点。生产流量会暴露测试集没有覆盖的问题。
- 必须监控: 每次检索的 Recall(在线代理指标)/ 用户满意度 / 响应延迟
- 持续更新数据集: 把生产中的 badcase 手工标注后加入黄金数据集
- 知识库更新策略: 增量入库(只算新文档的 embedding)/ 不重算全库
- 定期重评估: 每月用最新黄金数据集跑一次完整评估,防止指标悄悄退化
02 失败模式分类手册
读完 30~100 条 badcase 后的规律总结
这里的失败模式来自实践归纳。遇到新的 badcase 时,先对照这个分类找根因,不要上来就换模型——80% 的问题出在数据和检索上,不在生成上。
检索层 · F-01 召回缺失(Miss)
症状:相关内容明明在知识库里,但就是没被检索到。模型要么说不知道,要么用训练数据凑答案。
根因:
- ① 分块太小,关键信息被切断
- ② Embedding 模型不适配领域语言
- ③ 专有名词、缩写、产品型号被泛化
- ④ top-k 设置太小
修复方向:
- → 加大 chunk_size / 增加 overlap
- → 换领域适配的 Embedding 模型
- → 引入 BM25 混合检索(补关键词)
- → 增加 top-k,配合 Reranker 精排
检索层 · F-02 噪声命中(Noise)
症状:检索到了内容,但返回的 chunk 大量不相关,稀释了真正有用的信息。模型被噪声干扰,答案跑偏。
根因:
- ① 分块太大,一个 chunk 包含多个主题
- ② top-k 设置太大
- ③ 相似度阈值太低,不相关 chunk 也被召回
修复方向:
- → 减小 chunk_size,使每块主题单一
- → 加入相似度阈值过滤(< 0.7 直接丢弃)
- → 引入 Reranker 做二次精排
- → 使用 Parent-Child 分块策略
检索层 · F-03 排序错误(Misrank)
症状:正确答案被召回了,但没排在前面(排在 Top-3 以外)。LLM 处理上下文时更关注靠前的内容,答案质量因此下降。
根因:
- ① Bi-encoder 语义相似度打分不精准
- ② 查询和正确答案表达方式差异大
- ③ 关键词命中率影响了排序
修复方向:
- → 引入 Cross-encoder Reranker(精排专用)
- → 查询改写(让 query 更贴近文档表达)
- → 实验 HyDE(先生成假设答案再检索)
生成层 · F-04 上下文幻觉(Hallucination)
症状:检索到了正确内容,但 LLM 没有完全基于它回答,混入了训练数据里的”记忆”,造成细节错误。
根因:
- ① System Prompt 约束不够强
- ② 参考资料与训练数据有矛盾
- ③ 模型倾向于”补全”而非”引用”
修复方向:
- → 强化 Prompt:“只能基于以下资料回答,不得添加资料外的内容”
- → 要求模型引用来源 [1][2]
- → 用 Faithfulness 指标自动检测幻觉
生成层 · F-05 答非所问(Irrelevance)
症状:技术上检索和生成都”成功”了,但回答没有切中用户真正的问题。用户说”有帮助”但”不是我要的”。
根因:
- ① 用户意图模糊,没有做查询理解
- ② Prompt 没有引导模型聚焦核心问题
- ③ 回答过于发散
修复方向:
- → 澄清模糊 query(让模型先确认理解)
- → 加强 Prompt 中的”聚焦”指令
- → 用 Answer Relevancy 指标检测
系统层 · F-06 知识库过时(Staleness)
症状:回答内容在技术上是准确的,但基于的是旧版本的文档。产品已更新,文档没更新,导致误导用户。
根因:
- ① 没有文档版本管理机制
- ② 增量更新流程缺失
- ③ 旧文档没有被标记或删除
修复方向:
- → 为每个 chunk 附加 metadata:version, updated_at
- → 检索时过滤旧版本文档
- → 建立文档变更触发的自动重入库流程
系统层 · F-07 多跳缺失(Multi-hop Failure)
症状:问题需要综合两份不同文档的信息才能回答,但单次检索只拿到了其中一份,答案不完整。
根因:
- ① 单次检索设计,无法处理跨文档推理
- ② 用户问题包含隐式依赖关系
修复方向:
- → 实现 Multi-hop RAG:第一次检索结果作为第二次检索的 query
- → 引入 Agentic RAG,让模型自主决定检索次数
- → 构建知识图谱(GraphRAG)
系统层 · F-08 超出知识库(Out of Scope)
症状:用户问的问题知识库里根本没有,但系统没有识别出来,而是用相关度最高但不准确的 chunk 凑了一个答案。
根因:
- ① 没有相似度阈值判断”是否能回答”
- ② 没有设计拒答逻辑
修复方向:
- → 设置相似度阈值:全部 chunk 得分低于阈值 → 触发”超出知识库”回复
- → Prompt 中明确指示:“如果资料中没有,必须说不知道”
- → 定期分析”知识盲点”并补充文档
03 实验记录模板
一次只改一个变量
实验的核心纪律: 每次实验只改一个变量。改了两个变量,你不知道哪个起作用,下次就不知道该保留哪个。“感觉更好了”不是结论,数字说话。
实验日志示例(用于记录课程 v1→v10 的迭代过程)
| 版本 | 变更内容 | Recall@3 变化 | MRR 变化 | 结论 / 备注 |
|---|---|---|---|---|
| v3 基线 | ChromaDB + chunk=200 + overlap=40 + text-embedding-3-small | — (基线) | — (基线) | 建立基线数字,后续所有版本与此对比 |
| v4-exp1 | Embedding 换成 BGE-M3(中文领域模型) | +0.08 ↑ | +0.05 ↑ | 中文专业术语场景显著提升;通用问题基本持平;API成本降低 |
| v4-exp2 | Embedding 换成 text-embedding-3-large(更大维度) | +0.03 ↑ | +0.01 ↑ | 提升有限,但成本翻倍。不值得,回退到 exp1 的 BGE-M3 |
| v5-exp1 | 加入 BM25 混合检索(alpha=0.5) | +0.12 ↑ | +0.09 ↑ | 专有名词、产品型号 query 命中率大幅提升;通用 query 无明显变化 |
| v5-exp2 | 调整 alpha=0.3(减少 BM25 权重) | -0.02 ↓ | -0.01 ↓ | alpha=0.5 是更好的配置,保留 |
| v6-exp1 | 加入 bge-reranker(召回 Top-20,精排取 Top-3) | +0.06 ↑ | +0.15 ↑ | MRR 提升显著,正确答案排名更靠前;p99 延迟增加 300ms |
| v7-exp1 | 加入 HyDE 查询改写 | +0.05 ↑ | +0.04 ↑ | 概念性问题提升明显;事实性问题提升不大;额外增加一次 LLM 调用成本 |
实验纪律: 每次实验只改一个变量 · 同一数据集(开发集)评估 · 记录延迟和成本变化 · 所有实验结果保留,不删除”失败”记录
评估指标速查
| 指标 | 公式 | 说明 |
|---|---|---|
| Recall @ K | 命中数 / 查询总数 | 前 K 个结果里有没有包含正确答案。最重要的检索指标——天花板由此决定。 |
| MRR | avg(1 / rank) | 相关文档排在第几位。不只看”找到了”,还看”排在哪里”。 |
| Faithfulness | RAGAS 框架 | 生成的答案有没有忠实于检索资料,没有编造内容。反映幻觉程度。 |
| Answer Relevancy | RAGAS 框架 | 答案有没有切中用户问题。检索和生成都正确,但答非所问仍算失败。 |
04 项目启动检查清单
开始写代码之前必须全部过一遍
业务定义(第 0 步)
- 用户是谁已明确(具体到角色,不是”企业用户”)
- 具体用例已定义(单一用例,不是”全能助手”)
- 数据源清单已确认(1~2 个,有访问权限)
- 6 周成功标准已书面定义(量化指标)
- 数据安全 / 合规要求已了解(是否涉及敏感数据)
评估准备(在写代码前)
- 黄金数据集至少 20 条已准备(手标优先)
- 开发集 / 测试集已拆分(测试集已封存)
- Recall@K 和 MRR 评估脚本已可运行
- 基线评估已完成并记录(有数字才能比对)
检索系统
- 分块策略已选定并有数字支撑(对比实验完成)
- Embedding 模型已选定(中文场景考虑 BGE 系列)
- 向量数据库已配置(含 metadata schema 设计)
- 相似度阈值已设定(低于阈值触发拒答逻辑)
生产准备
- 已完成 30+ 条手动错误分析(找到主要失败模式)
- 主要失败模式已有自动化检测(代码或 LLM-judge)
- 延迟 p50/p99 已测量(知道用户实际等待时间)
- 成本估算完成(每月 embedding + LLM token 费用)
- 测试集最终评估完成(用且仅用一次)
05 RAG 方案边界
知道什么时候不该用 RAG,和知道什么时候该用同样重要
RAG 不是银弹。向客户推荐方案时,如果你能说出”这个场景用 RAG 反而不合适,因为……”,你的专业度会立刻比只会推 RAG 的人高出一个档次。
| 场景 | 推荐方案 | 不推荐 | 判断依据 |
|---|---|---|---|
| 知识库有限(< 50 页),内容稳定,问题类型固定 | Fine-tuning 或 Prompt Engineering | RAG 过度设计 | 内容少到可以直接放进 System Prompt,RAG 带来的工程复杂度不值得 |
| 私有文档频繁更新(每天有新内容),不能有知识截止 | RAG(增量入库) | Fine-tuning(更新成本太高) | Fine-tuning 每次更新都要重新训练,成本不可接受;RAG 只需要增量 embedding |
| 问题需要精确数字推理(财务计算、代码执行) | Tool Use + 结构化数据库查询 | 纯 RAG(检索文本,无法精确计算) | LLM 算数不可靠;结构化数据应该用 SQL/API 查询,不是向量检索 |
| 知识库超大(百万级文档),延迟敏感(< 200ms) | RAG + 语义缓存 + ANN 优化 + 向量库分级存储 | 朴素 RAG(单节点、无缓存) | 朴素 RAG 在大规模下延迟不可控;需要工程优化 |
| 多文档综合推理(需要跨 5+ 个文档才能回答一个问题) | GraphRAG 或 Agentic RAG(多跳) | 经典单跳 RAG(一次检索搞不定) | 单次检索只能召回局部信息;需要有状态的多轮检索或知识图谱 |
| 高安全合规要求(金融、医疗),不能有任何幻觉 | RAG + 强 Faithfulness 检测 + 人工审核机制 | 完全自动化无人工节点 | LLM 幻觉无法完全消除;高风险场景必须有人工审核兜底 |
06 售前背景的核心差异化
工程能力 + 业务理解 = 稀缺组合
纯工程师知道怎么写代码,但不知道这个系统在业务上解决了什么问题,也不知道怎么向客户解释技术决策。这正是你的优势所在。
能力 01 · 从业务需求推导技术方案
客户说”我们想做知识库问答”,你能问出”用户是谁、问的是什么类型的问题、数据在哪里”——这三个问题比直接写代码更重要,也是方法论第 0 步的核心。这是大多数工程师问不出来的问题。
能力 02 · 量化标准 → 项目提案
黄金数据集的方法论直接对应项目提案的”成功指标”章节。你可以在方案里写:“第 2 周交付 30 条黄金数据集和基线 Recall@3;第 4 周目标 Recall@3 > 0.85”——这是可落地的承诺,不是模糊的”提升效率”。
能力 03 · 向非技术人员解释技术决策
你能用”这个方案的边界在哪里”这张表,向客户解释为什么推荐 RAG 而不是 Fine-tuning,为什么选混合检索而不是纯向量。这不是炫技,是建立信任——客户需要知道你理解他们的场景,不是在卖技术方案。
综合优势 · 最有价值的产出:可复用的工程资产
每个项目积累的东西:黄金数据集(下个项目可参考结构)、失败模式记录(形成 checklist)、实验日志(形成决策依据)、方案边界文档(形成销售材料)。
这些不只是技术文档,也是下一个项目的提案素材——“我们在类似场景做过,Recall@3 从 0.62 提升到 0.89,用的是这套方法论”。这才是售前转型后真正的核心竞争力。
关联阅读
- 要回到组件全貌:去知识地图看模块关系。
- 要解释方案边界:去 5D 完全理解看对比、场景和常见误区。
- 要快速找概念和参数:去文档索引。