📑 本页目录(点开跳转)
08 · RAG 深水区
⏱ 76 分钟 | ⭐⭐⭐ 落地场景最多的一块
🎯 一句话
RAG 的 demo 版本一小时能搭出来,生产版本能做三个月。差距不在「向量检索」这四个字,而在切分、混合检索、重排、查询改写、评估这一整条链路。 而这条链路上最容易被搞反的是顺序:先做切分和混合检索,再加重排,最后才轮到换 embedding 模型。
😅 先看差距有多大
【Demo 版 RAG】—— 一小时搞定,效果 60 分
文档 → 每 500 字切一块 → 向量化 → 存库
问题 → 向量化 → 找最像的 5 块 → 塞进提示词 → 回答
【生产版 RAG】—— 每一环都是坑
文档 → 解析(PDF表格/图片?) → 语义切分 → 补上下文 → 多路索引
↓
问题 → 意图识别 → 查询改写/扩展 → 混合检索(向量+关键词)
→ 粗排 100 → Cross-Encoder 重排 10 → 上下文压缩
→ 生成 → 引用溯源 → 幻觉检测 → 评估回流
🔗 看出来了吗:这个漏斗结构和推荐算法第 6 章的召回→粗排→精排→重排一模一样。 RAG 本质上就是一个搜索系统。 ⭐ 做过推荐或搜索的人,那套知识在这里可以直接迁移 (本站《推荐算法》讲的就是这一套);没做过也不必绕路,这一章会把漏斗每一环都讲一遍。
🧱 环节一:切分(最被低估的一环)
❌ 固定长度切分(每 500 字一刀)
→ 一句话被拦腰砍断、表格被切碎、上下文丢失
✅ 常用策略
├─ 按结构切:Markdown 标题、章节、段落 ← 优先
├─ 语义切分:相邻句子语义相似度突变处下刀
├─ 重叠窗口:块之间重叠 10–20%,防止边界信息丢失
└─ 父子块:检索用小块(精准),喂给模型用大块(完整)⭐ 很好用
⭐ 上下文检索(Contextual Retrieval)
一个简单但效果显著的技巧:给每个分块补一句「它在讲什么」的上下文说明再做向量化。
原始块:「该季度收入增长 3%。」
↑ 单独看:哪个公司?哪个季度?检索不到
补充后:「本段出自 ACME 公司 2024 Q2 财报,讨论季度业绩。
该季度收入增长 3%。」
↑ 现在能被「ACME 2024 收入」这样的问题检索到 ✅
📌 官方博客的数据:这个方法能让检索失败率下降约 49%(配合重排更多)。 成本是用小模型给每个块生成一句上下文——一次性投入,长期收益。
📏 块大小怎么定(一个实用的起点)
太小(<200 字)→ 每块信息不完整,检索到了也答不了
太大(>2000 字)→ 一块里混了多个主题,向量被"平均"掉,检索不准 ⭐
⭐ 起点建议:
· 通用文档 300~800 字
· 技术文档 按代码块/函数/小节切,别按字数
· 法律/合同 按条款切,一条一块
· FAQ 一问一答就是一块(天然最好切的)
⚠️ 但真正该做的是:【拿你自己的 20 个真实问题测三档,看哪档 Recall 高】
💡 为什么"太大反而不准"值得单独说:
一个块的 embedding 是它整体语义的平均。 塞进三个不同主题,这个向量就落在三者中间的"没人区"—— 对哪个主题的问题都不够近。 这是很多人调不好 RAG 的隐形原因。
🔗 高维向量的一个反直觉陷阱
🔗 《数学原理》第 5 章 维度灾难有个实测数字: 在 500 维空间里,最远的点和最近的点距离只差 19%。
含义:向量维度很高时,「最近邻」这个概念本身在变弱—— 所有东西看起来都差不多远。这就是为什么: - ✅ 必须配 BM25(字面匹配不受维度灾难影响) - ✅ 必须配重排(Cross-Encoder 不依赖向量距离) - ❌ 只靠调 embedding 模型救不回来
🔍 环节二:混合检索(别只用向量)
向量检索(语义) 关键词检索 BM25(字面)
✅ 懂同义、懂意图 ✅ 精确匹配术语、型号、人名、代码
❌ 精确的专有名词反而不准 ❌ 不懂同义词
例:查「XR-2000 的功率」
向量检索可能找到「XR-3000 的功率」(语义相近但答案错误!)
BM25 能精确锁定 XR-2000 ✅
结论:两路都要,然后融合。常用 RRF(倒数排名融合)——不需要分数可比,只用排名。
$$\text{RRF}(d) = \sum_{r \in \text{检索器}} \frac{1}{k + \text{rank}_r(d)}$$
💡 人话:每个文档在各路检索里的排名越靠前,得分越高,加起来排序。简单粗暴但极其有效。
🎯 环节三:重排(性价比最高的一步)
双塔 Embedding(检索用) Cross-Encoder(重排用)
问题和文档分别编码,点积 问题和文档拼在一起过模型
✅ 快,能扫全库 ✅ 准得多(能做深度交互)
❌ 不能做深度交互 ❌ 慢,只能处理几十上百条
→ 先用向量+BM25 召回 100 条,再用 Cross-Encoder 精排出 10 条
🔗 完全是推荐算法第 8 章的「双塔做召回、精排做交叉」。同一套思想。
这一步通常是投入产出比最高的优化——加一个重排模型,往往比换更好的 embedding 模型收益大。
🥊 Cross-Encoder / ColBERT / LLM:三种重排怎么选
"重排"不是一种东西,是三条不同的路线。它们的核心差别只有一个:问题和文档在什么时候相遇。
| 路线 | 问题和文档什么时候相遇 | 文档能预计算吗 | 100 条候选的延迟 | 效果 | 什么时候选它 |
|---|---|---|---|---|---|
| 双塔 Embedding(对照组,不是重排) | 从不 —— 各自编码成一个向量,最后才点积 | ✅ 全部离线 | ≈ 0(它就是检索本身) | 基线 | 召回阶段 |
| Cross-Encoder | 最早 —— 拼成一条输入一起过模型 | ❌ 一条都不能 | 几十~几百毫秒 | ⭐ 最好 | 绝大多数场景的默认答案 |
| ColBERT(后期交互) | 中间 —— 各自编码成 token 级向量矩阵,查询时才交互 | ✅ 文档侧可离线 | 个位数毫秒 | 介于两者之间 | 候选量大到 Cross-Encoder 跑不动 |
| LLM 重排 | 最早,而且是"读懂了再排" | ❌ | 秒级 + token 账单 | 复杂/多条件问题上最好 | 候选很少(20 条以内)、单次价值高 |
ColBERT 的机制值得单独说清楚(它是这三条里最容易讲错的):
Cross-Encoder:[问题 + 文档] 拼一起进模型 → 一个分数
→ 100 条候选 = 100 次前向,全在线算 → 贵
ColBERT:问题编成 Q 个向量,文档编成 D 个向量(每个 token 一个)
分数 = 对每个【问题 token】,取它和所有【文档 token】里最像的那个
的相似度,然后全部加起来 ← 这就是 MaxSim
→ 文档那 D 个向量【可以离线算好存起来】⭐
→ 在线只剩一堆点积,比 Cross-Encoder 快一到两个数量级
⚠️ 代价是存储爆炸:一个块从「1 个向量」变成「几百个向量」,
索引体积膨胀一个数量级。ColBERTv2 用残差压缩把它压回来一些,
但仍然远大于单向量索引。
🔑 一句话选型:默认 Cross-Encoder。 只有"候选太多、Cross-Encoder 跑不动"才上 ColBERT(拿存储换延迟); 只有"候选很少但问题很绕"才上 LLM 重排(拿钱换效果)。 ⚠️ 别从 ColBERT 开始——它解决的是规模问题,不是效果问题。用它替代 Cross-Encoder 通常是效果的降级。
💡 LLM 重排还有一个更划算的用法:不当线上重排器,而当离线评测集的标注器——让它给 100 个问题的召回结果打分,人再抽查 10%。线上跑不起的成本,离线跑得起。
🧭 Embedding 选型:排在重排之后的那件事
先把这一节的位置摆正。 前面已经说过两次同一件事:
- 环节一:高维空间里「最近邻」这个概念本身在变弱,只靠调 embedding 模型救不回来
- 环节三:加一个重排模型,往往比换更好的 embedding 收益大
所以正确顺序是 切分 → 混合检索 → 重排 → 然后才轮到换 embedding。 这一节回答的是"轮到了之后怎么选",不是"一上来先选哪个"。
什么时候是真的该换了
| 信号 | 说明 |
|---|---|
| ⭐ 语种不对 | 拿纯英文模型跑中文——这不是"效果差一点",是根本不该出现的配置错误。中文/多语言场景先确认模型的训练语料覆盖 |
| ⭐ 领域词汇完全在分布外 | 医学、法律、化学式、内部工单代号。通用模型没见过这些词,它们的向量互相挤在一起,怎么调都分不开 |
| ⚠️ 文本长度对不上 | 模型 max_seq_len 是 512 token,你的块是 1000 字 → 超出部分被静默截断。你以为在检索整块,其实只检索了前半块。这个坑最隐蔽,因为它不报错 |
| 非对称检索没用对姿势 | 「短问题查长文档」是非对称任务,很多模型要求给 query 和 document 加不同的前缀(instruction),不加就掉点。这是配置问题,不是模型问题 |
维度怎么取舍(768 / 1024 / 1536)
维度 ↑ → 表达能力略强,但【边际收益递减很快】
→ 存储、内存、ANN 检索延迟【线性增长】
100 万块 × 1536 维 × 4 字节 = 6.1 GB (还没算索引结构本身)
100 万块 × 768 维 × 4 字节 = 3.1 GB
⭐ 判断顺序(不要反过来):
先量出 1536 维比 768 维在【你自己那 20 个问题】上高几个点,
再问这几个点值不值 2 倍存储 + 更慢的检索。
多数企业知识库场景:不值。
💡 一个常被忽略的选项:MRL(套娃表示)。有些模型在训练时就让"前 256 维"自己也是一个能用的向量,于是同一份 embedding 可以截断后粗筛、完整维度精算,存储和延迟一起省。选型时留意模型卡上有没有这一条。
MTEB 榜怎么看(榜首≠对你最好)
- ⭐ 看子任务,不看总分。 MTEB 总分把分类、聚类、语义相似度、检索混在一起平均。你只关心 Retrieval 那一栏;中文看 C-MTEB 的检索子集。
- 顺手看"参数量"和"维度"两列。 榜首常是 7B 级的 embedding 模型——它的推理成本可能比你整条检索链路还高。
- ⚠️ 榜单会被刷。 训练数据里混进评测集是这个榜公开的老问题。一个模型只在榜上好、在你那 20 个问题上不好,信你自己的。
- 别忘了迁移成本:换 embedding 意味着全库重算向量 + 重建索引。100 万块重跑一遍是实打实的钱和时间。
什么时候值得领域微调
⭐ 判据不是"效果不够好",而是"通用模型分不开你的两类文档"。
| 情况 | 建议 |
|---|---|
| 领域术语密集,且有 1000 条以上「问题 → 正确文档」的真实数据(可以从线上点击日志里挖) | ✅ 值得试 |
| 只有几百条 | 🟡 先试指令前缀和领域词典做查询扩展,成本低一个数量级 |
| 还没做混合检索和重排 | ❌ 顺序错了,回去做那两件 |
🔗 微调 embedding 用的就是对比学习 + in-batch 负采样 + 温度系数,和推荐算法第 8 章的双塔训练是同一套方法,连坑都一样:负样本选错(用"曝光未点击"当负样本会训废)、热门项支配(要 LogQ 校正)、温度系数 τ 从 0.05 开始调。要动手微调之前先去读那一节。
🚨 最后一条是运维铁律:换了 embedding 模型,全库必须重建索引。 新旧模型的向量空间不通用,混在一个索引里检索结果是乱的——而且不报错,只是变差。 灰度期必须双索引并行(新旧各一份,按流量切),不能原地替换。
🔄 环节四:查询侧处理
| 技巧 | 做什么 | 解决 |
|---|---|---|
| 查询改写 | 把口语化问题改成检索友好的 | 「上次说的那个咋样了」→ 无法检索 |
| 多查询扩展 | 一个问题生成 3–5 个变体分别检索 | 单一表述漏召回 |
| HyDE | 先让模型假装回答,用假答案去检索 | 问题和答案的表述差异大 |
| 意图路由 | 判断该查文档、查数据库、还是直接答 | 不是所有问题都需要 RAG |
| 多跳检索 | 检索→发现缺信息→再检索 | 需要串联多个事实的问题 |
💡 HyDE 的巧妙之处:问题「怎么申请报销」和文档「报销流程:第一步…」在向量空间里未必近; 但模型编的假答案「报销需要先填单据…」和真文档就很近了。
📊 环节五:评估(最容易被跳过,也最致命)
必须分开评估两段,否则你不知道问题出在哪:
① 检索质量:正确答案在召回结果里吗?
指标:Recall@K、MRR、NDCG ← 推荐算法第 12 章的老朋友
② 生成质量:
· 忠实度 Faithfulness —— 答案是否只基于检索到的内容(防幻觉)⭐
· 答案相关性 —— 答案是否真的回答了问题
· 上下文相关性 —— 召回的内容是否真的有用
⚠️ 最常见的诊断错误:答案不对就去调提示词。 先查检索——如果正确文档根本没被召回,提示词再怎么调都没用。
📐 RAGAS 的四个指标(把上面三条补齐)
上面列的三条全是生成侧的。面试最常问的 RAGAS 四指标里,还有一个是检索侧的,也是最容易被漏掉的那个:
| 指标 | 它问的是什么 | 分低说明 | 属于哪一段 |
|---|---|---|---|
faithfulness忠实度 |
答案里的每一句,都能在召回的上下文里找到依据吗 | 模型在编 | 生成 |
answer_relevancy答案相关性 |
答案是在回答这个问题吗(不是"对不对",是"答没答") | 答跑题了 / 车轱辘话 | 生成 |
context_precision上下文精确率 |
召回的那几块里,有用的排在前面吗 | 重排缺失或没做好,正确文档排太后 | 检索 |
context_recall上下文召回率 |
标准答案需要的信息,都被召回了吗 | 压根没捞到——切分不当 / 缺 BM25 / 表述差异 | 检索 ⭐ |
⭐ 四个里最该先看
context_recall。 它是唯一需要标准答案才能算的指标(另外三个只要 问题 + 上下文 + 答案 就能算),也是唯一能告诉你"信息压根没进来"的指标。 上面那条铁律「答案不对先查检索」,量化出来就是它。⚠️
context_precision和context_recall千万别搞反: recall 低 = 没捞到(要改切分和检索);precision 低 = 捞到了但埋在噪声里(要加重排)。 这两条的处方完全不同,认错了就会一直修错的那一环。
⚠️ RAGAS 这四个分数多数是靠 LLM 打出来的,所以它自带 LLM-as-a-Judge 的全部毛病:分数随裁判模型版本漂移、成本按 token 计、同一批数据两次跑结果不完全一样。 把它当"趋势指标"用(这次改动比上次高了吗),别当"绝对分数"用——「我们的 faithfulness 是 0.87」这句话离开了裁判模型和版本就没有意义。
🩺 一张诊断表(照着查,5 分钟定位问题)
| 现象 | 先查这个 | 大概率的根因 | 哪个指标会先亮红灯 |
|---|---|---|---|
| 答案完全跑偏 | 召回结果里有正确文档吗? | 检索问题:切分不当 / 缺 BM25 / 查询表述差异大 | context_recall |
| 召回里有正确文档,但答案还是错 | 它排第几? | 重排缺失——正确文档排在第 15 位,被截断了 ⭐ | context_precision |
| 答案对但编了引用 | 提示词有没有强制"只用给定内容" | 生成侧幻觉,要加约束 + 引用校验 | faithfulness |
| 答案太笼统 | 召回的块是不是太大 | 块里混了多个主题,模型抓不住重点 | answer_relevancy |
| 专有名词/型号查不到 | 有没有 BM25 | 纯向量检索的典型失败 ⭐ | context_recall |
| 时效性内容答错 | 索引多久更新一次 | 索引腐烂——文档更新了但没重建 | context_recall(症状而已,根因在索引管线) |
| 别人的数据被查出来了 | 有没有做行级权限过滤 | 🚨 合规事故(第 14 章) | ⚠️ 一个都不会亮 |
🚨 盯住最后一行:RAGAS 四个指标一个都发现不了权限越权。 被越权召回的文档"内容相关、答案忠实、引用属实"——四项全绿,评估体系完全无感。 合规只能靠专门的权限测试用例(拿 A 用户的身份去问只有 B 能看的问题,断言召回为空),指标救不了你。 ⭐ 这条推广出去是一条通用教训:你的指标体系只会告诉你它被设计来测的东西。
🔑 最有价值的一个习惯: 每次 RAG 回答错了,都把"召回的原始块"打印出来看一眼。 十次里有七次,你会发现问题根本不在生成侧。
🔨 一个最小可用的评估脚本
# 只需要 20 条 (问题, 正确文档ID) 就能开始
def eval_retrieval(qa_pairs, retrieve, k=10):
hits, ranks = 0, []
for q, gold_id in qa_pairs:
ids = [d.id for d in retrieve(q, k=k)]
if gold_id in ids:
hits += 1
ranks.append(1 / (ids.index(gold_id) + 1)) # MRR
else:
ranks.append(0)
print(f"Recall@{k} = {hits/len(qa_pairs):.1%} MRR = {sum(ranks)/len(ranks):.3f}")
💡 有了这 10 行,你的每一次改动才有了意义—— 否则"我觉得加了重排好像好一点"永远只是感觉。 🔗 这条纪律来自《机器学习基础》第 5 章和 Kaggle 教程。
🛑 读到这里可以停 —— 五个环节加上 Embedding 选型都讲完了(约 36 分钟),主线到此为止。 后半章还有:GraphRAG / Agentic RAG / Self-RAG / CRAG 四条进阶路线各自的代价 · 和推荐算法知识的对应表 · 深挖清单 · 要不要深挖的判断 回来的时候不用重读,直接从下一节接着看就行。
🕸️ 进阶方向:GraphRAG / Agentic RAG / Self-RAG / CRAG
⭐ 每一行都写了代价 —— 这些方向的资料通常只讲好处,而真正决定要不要上的是右边那一列。
| 方向 | 解决什么 | 代价 |
|---|---|---|
| GraphRAG | 构建实体关系图,回答「跨多个文档的全局性问题」(如「这些报告的共同主题是什么」) | 建图要把全库过一遍 LLM,索引成本高一到两个数量级;而且图建好之后很难增量维护——文档一改,关系可能全变 |
| Agentic RAG | 让 Agent 自己决定检索几次、检索什么(智能体教程的循环 + RAG) | 延迟和 token 从"一次检索"变成"若干轮";必须有显式步数上限,否则会绕圈 |
| Self-RAG | 让模型自己判断"这次要不要检索"和"检回来的有没有用":训练时就往输出里加入反思标记(要不要检索 / 相不相关 / 有没有被支持),生成时按标记走分支 | ⚠️ 要微调模型才能产生这些标记,通用 API 模型用不了原版;用提示词模拟会明显打折 |
| CRAG(Corrective RAG) | 给召回结果加一个轻量评估器打分:好 → 直接用;差 → 回退到网络搜索;不确定 → 两者混合。本质是"检索质量的兜底闸门" | 多一个评估器(延迟 + 成本);回退到外部搜索意味着答案可能来自不可控来源,企业内网场景要谨慎 |
| 多模态 RAG | 检索图片、表格、图表(第 10 章) | 需要多模态 embedding + 版面解析,整条链路变重 |
| 长上下文 vs RAG | 上下文变长后还需要 RAG 吗?→ 需要:成本、时效、可溯源、规模 | — |
🔑 Self-RAG 和 CRAG 其实是同一个念头的两种实现:都在给 RAG 加一道「这次检索到底靠不靠谱」的判断。 区别是 Self-RAG 把判断力训进模型里(要微调),CRAG 把判断力放在模型外面(一个可插拔的评估器)。
⭐ 工程上先做 CRAG 那一路:它不动模型,加一个打分阈值就能上线,是这两条里投入产出比高得多的一条。而且它的评估器和你上面那张诊断表想量化的是同一件事——只不过从"事后排查"变成了"事中拦截"。
🔗 和你已知的关系
⭐ RAG 是全导论迁移余地最大的一块,但迁移是有条件的——对上了是白赚,没对上也不影响学(它同时是门槛最低的几章之一):
| 如果你已经知道 | 那么在这一章它对应什么 |
|---|---|
| 召回→粗排→精排→重排(推荐算法 06) | RAG 是同一个漏斗 |
| 双塔召回 + 精排交叉(推荐算法 08) | Embedding 检索 + Cross-Encoder 重排 |
| Recall@K / NDCG(推荐算法 12) | 检索侧评估直接用 |
| 向量检索 ANN(推荐算法 10) | RAG 的基础设施完全相同 |
| RAG 入门(智能体工程 11) | 那是入门,这一章是它的完整版 |
🔑 做过推荐或搜索的人,在 RAG 上等于开局领先半场——那一套搜索/排序知识至少一半可以直接用。 没做过也别绕路:上表右列就是你要学的东西本身,只是别人已经在另一个领域学过一遍而已。
📦 深挖的话要学什么
✅ = 本章正文已经讲了,点进去就是;其余是本章之外的。
📍 本章之外的那些,也标了它在哪: 📗 本库有 = 站内已经讲透,点进去就行;📙 半有 = 站内讲了一半,另一半得外找; 📕 要外找 = 站内没有,得去论文或别处。 (这份清单以前只列词不说去哪,指到的坑有些站内根本没挖过,按图索骥会扑空。)
- 文档解析:PDF/表格/扫描件(OCR)、版面分析、Markdown 转换 → 📕 要外找:站内一个字都没有。⚠️ 这一条值得单独警惕——它排在整条链的第一位,做企业知识库时也常常是最耗时的一环,而本库帮不上忙。别因为它在清单第一行就以为它最简单
- 切分:语义切分算法的阈值怎么定、Late Chunking、上下文补全的成本控制 → 📙 半有:切分的实用判据本章自己给了(块大小起点、上下文检索/Contextual Retrieval 的做法)。Late Chunking 和语义切分算法的阈值调法站内没有,要外找
- Embedding:✅ 选型判据与维度取舍 | 领域微调的数据怎么攒、跨语言检索、MRL 截断检索 → 📙 半有:「领域微调的数据怎么攒」本质是标注问题,数据这一关 09 · 标注体系怎么设计 和 12 · 标注预算与主动学习 讲的正是"用有限预算攒出有用的标注"。MRL 截断检索和跨语言检索站内没有,要外找
- 检索:BM25 的公式本身(tf-idf、k1、b)、SPLADE 学习式稀疏检索、向量库选型(Milvus/Qdrant/pgvector,见推荐算法第 10 章) → 📙 半有:向量库选型 📗 就是上面那条链接;BM25 怎么用在 智能体工程 11 · 检索与RAG(为什么查「XR-2000」时向量会返回「XR-3000」、以及 RRF 融合为什么不需要分数可比)。但 BM25 的公式本身(k1、b 怎么调)和 SPLADE 站内没有,要外找
- 重排:✅ Cross-Encoder / ColBERT / LLM 三条路线 | ColBERTv2 的残差压缩、ColPali(直接对页面截图做后期交互) → 📕 要外找:⚠️ 全站搜「ColBERT」,唯一的正文出处就是本章上面那一节——ColBERTv2 和 ColPali 站内彻底没有,去 ColBERT 项目仓库
- 查询理解:改写、扩展、HyDE、路由、多跳(本章环节四给了地图,每一项都还能深挖) → 📗 本库有(HyDE 这一项):智能体工程 11 · 检索与RAG 把 HyDE 讲透了——问题「怎么申请报销」和文档「报销流程:第一步…」在向量空间里未必近,但模型编的假答案和真文档就很近。其余(改写/扩展/路由/多跳)本章的地图已经是站内最全的版本,再深挖要外找
- 生成:引用溯源怎么校验、幻觉检测、上下文压缩(LLMLingua)、拒答策略 → 📙 半有:拒答和输出把关这一侧站内很实在——智能体工程 16c · 接进真实产品 讲三层护栏、审核该放在链路哪个位置,⚠️ 还有一次事故复盘:审核只在末尾做,有害内容已经吐了 3.2 秒(做流式 RAG 的话这条直接适用)。但引用溯源的自动校验和 LLMLingua 式上下文压缩,站内没有,要外找
- 评估:✅ RAGAS 四指标 | 构建自己的测试集、端到端 vs 分段评估、TruLens / DeepEval / promptfoo 的差别 → 📙 半有:「构建自己的测试集」📗 站内很强——智能体工程 14 · 评测Evals 的八步(最贵的是写无歧义任务+参考解和读转录),加 数据这一关 13 · 评测集也是数据(抽样、多大才够、评分器也要校准)。工具那一侧 智能体工程 16b · 框架这层皮 说清了 Ragas / promptfoo / DeepEval 替你做的只是"评分器实现 + 跑批出表",最贵的三步一步不管。只有三者之间的具体差别要外找
- 进阶:✅ GraphRAG / Agentic RAG / Self-RAG / CRAG 及各自的代价 | 知识图谱怎么抽实体关系、增量索引与更新策略 → 📕 要外找:⚠️ 别被「知识图谱」这个词在站内的搜索结果骗了——Kaggle 19 里的知识图谱是推荐系统的物品关系图,和 GraphRAG 的实体抽取不是一回事。实体关系抽取和增量索引站内没有,从 GraphRAG 项目文档开始
需要的前置:不需要 GPU、不需要新数学,会调 API 就能开始。⭐ 做过推荐/搜索或写过 Agent 的人几乎是零前置(站内《推荐算法》《智能体工程教程》覆盖的就是这两块);没有这些背景的人,前置也只是「会用向量数据库存取一次数据」。
⚖️ 要不要深挖
| 你的情况 | 建议 |
|---|---|
| 要做企业知识库/客服/文档问答 | ✅ 必须,且优先级最高 |
| 做任何需要「模型用上私有数据」的事 | ✅ 必须(比微调重要得多) |
| 只做通用对话应用 | 🟡 知道基础即可 |
| 想快速产出可用成果 | ✅ 这块见效最快 |
🔑 我的判断:如果只能深挖一块,从纯实用角度这块排第一: - 落地场景最多(企业知识库是当前最主流的 AI 落地形态) - 迁移余地最大(做过推荐/搜索的话,那套知识直接复用;没做过也是全表门槛最低的几块之一) - 见效最快(一周能做出可用的东西) - 不需要 GPU、不需要新数学
唯一的竞争者是第 2 章 Transformer 原理——那个是认知价值最高,这个是实用价值最高。
✅ 检查点
- RAG 的漏斗结构和推荐系统的什么结构对应?
- 块太大为什么反而检索不准?(说出机制)
- 高维向量的什么性质决定了「只调 embedding 模型救不回来」?该配什么?
- 为什么必须用混合检索而不能只用向量?
- 上下文检索(Contextual Retrieval)做了什么?效果如何?
- 为什么说重排是性价比最高的一步?
- RAG 答案不对,第一步该查什么?最有价值的排查习惯是什么?
- 「召回里有正确文档但答案还是错」——该查什么?
- HyDE 的原理是什么?
- Cross-Encoder、ColBERT、LLM 重排三条路线的核心差别是什么?默认该选哪个、为什么不该从 ColBERT 开始?
- ColBERT 的 MaxSim 是怎么算的?它换来了什么、代价是什么?
- 什么信号说明"该换 embedding 模型了"?换模型有一条什么运维铁律?
- RAGAS 的四个指标分别问什么?
context_precision低和context_recall低,处方有什么不同? - 为什么说 RAGAS 分数只能当"趋势指标"?
- 诊断表里哪一类问题是四个指标一个都不会亮的?该怎么查?
- Self-RAG 和 CRAG 在解决同一件什么事?两者的区别是什么?工程上先做哪个?
👀 答案
- 召回→粗排→精排→重排。RAG 本质是一个搜索系统。
- 一个块的 embedding 是它整体语义的平均。塞进三个主题,向量就落在三者中间的"没人区",对哪个主题的问题都不够近。
- 维度灾难——500 维时最远和最近的点距离只差 19%,「最近邻」这个概念本身在变弱。所以必须配 BM25(字面匹配不受影响)和重排(Cross-Encoder 不依赖向量距离)。
- 向量懂语义但对精确的专有名词/型号/代码不准(可能召回 XR-3000 而不是 XR-2000);BM25 精确匹配但不懂同义。两路融合(RRF,只用排名不用分数)互补。
- 给每个分块补一句"它在讲什么"的上下文说明再向量化,让孤立的块也能被检索到。官方数据检索失败率降约 49%。
- 双塔检索快但不能深度交互;Cross-Encoder 把问题和文档拼一起过模型,准得多。在已召回的几十条上重排,成本可控而收益大,通常比换 embedding 模型更划算。
- 先查检索——正确文档有没有被召回。最有价值的习惯:每次答错都把召回的原始块打印出来看一眼,十次里七次问题不在生成侧。
- 查它排第几——大概率是重排缺失,正确文档排在第 15 位被截断了。
- 先让模型假装回答生成一个"假答案",用假答案去检索。因为假答案和真文档的表述风格更接近,比原始问题更容易匹配上。
- 核心差别是问题和文档在什么时候相遇:Cross-Encoder 最早(拼一起过模型,文档一条都不能预计算,最准也最慢);ColBERT 在中间(各自编成 token 级向量,查询时才 MaxSim,文档侧可离线);LLM 重排是"读懂了再排"(秒级 + token 账单)。默认 Cross-Encoder。不该从 ColBERT 开始是因为它解决的是规模问题不是效果问题——拿它替代 Cross-Encoder 通常是效果的降级。
- 对每个问题 token,取它和所有文档 token 里最像的那个的相似度,全部加起来。换来的是文档那几百个向量可以离线算好,在线只剩点积,比 Cross-Encoder 快一到两个数量级。代价是存储爆炸:一个块从 1 个向量变成几百个向量,索引体积膨胀一个数量级(ColBERTv2 用残差压缩压回来一些)。
- 四个信号:语种不对(英文模型跑中文是配置错误不是效果问题)、领域词汇完全在分布外(医学/法律/工单代号)、⚠️块长超过模型
max_seq_len被静默截断(最隐蔽,因为不报错)、非对称检索没加 query/document 前缀。铁律:换 embedding 必须全库重建索引——新旧向量空间不通用,混在一个索引里检索结果会乱且不报错;灰度期要双索引并行。 faithfulness答案有没有依据(模型在编)、answer_relevancy答没答这个问题、context_precision有用的排没排在前面、context_recall需要的信息捞没捞到。recall 低 = 没捞到 → 改切分和检索;precision 低 = 捞到了但埋在噪声里 → 加重排。 处方完全不同,认错就一直修错的那一环。- 因为这四个分数多数是 LLM 打出来的,自带 LLM-as-a-Judge 的毛病:随裁判模型版本漂移、按 token 计费、同一批数据两次跑结果不完全一样。所以「我们的 faithfulness 是 0.87」离开裁判模型和版本就没有意义,只能比"这次改动比上次高了吗"。
- 权限越权(别人的数据被查出来)。被越权召回的文档内容相关、答案忠实、引用属实,四项全绿。只能靠专门的权限测试用例——拿 A 用户的身份去问只有 B 能看的问题,断言召回为空。通用教训:指标体系只会告诉你它被设计来测的东西。
- 都在给 RAG 加一道「这次检索靠不靠谱」的判断。区别是 Self-RAG 把判断力训进模型里(要微调,通用 API 模型用不了原版),CRAG 把判断力放在模型外面(一个可插拔的评估器,差就回退到网络搜索)。工程上先做 CRAG——不动模型,加个打分阈值就能上线。
🛑 可以停在这里
⚡ 走神救援
RAG demo一小时、生产三个月。本质是搜索系统,漏斗和推荐算法第6章一模一样→做过推荐/搜索的人迁移余地极大,没做过也是门槛最低的几章之一。五环节:①切分(按结构/父子块/上下文检索补说明,失败率降49%;⭐块太大反而不准——embedding是整体语义的平均,混三个主题就落在"没人区";起点300~800字但该拿20个真实问题测三档)②混合检索(向量+BM25用RRF融合,专有名词必须BM25;根因是维度灾难——500维时最远和最近只差19%,最近邻这个概念在变弱,所以光调embedding救不回来)③重排Cross-Encoder(性价比最高,通常比换embedding模型划算)④查询侧(改写/多查询/HyDE:让模型编个假答案去检索,因为假答案和真文档的表述更接近/路由/多跳)⑤评估(分开评检索和生成,答案不对先查检索;召回里有正确文档但答案错→查它排第几,多半是重排缺失被截断了;⭐最有价值的习惯:每次答错都打印召回的原始块,十次里七次问题不在生成侧;10行脚本+20条问答就能开始量化)。 重排的三条路线(差别就是问题和文档什么时候相遇):Cross-Encoder最早相遇(拼一起过模型,最准最慢,默认选它)、ColBERT后期交互(各自编成token级向量,查询时算MaxSim=每个问题token去文档里找最像的那个再求和,文档侧可离线所以快一到两个数量级,⚠️代价是一个块从1个向量变成几百个,索引膨胀一个数量级;⭐它解决规模问题不是效果问题,别从它开始)、LLM重排(秒级+token账单,更划算的用法是当离线评测集的标注器)。Embedding选型排在重排之后(顺序:切分→混合检索→重排→才轮到换模型):该换的信号是语种不对、领域词在分布外、⚠️块长超过max_seq_len被静默截断(不报错);维度先量收益再算代价(100万块×1536维=6.1GB,×768维=3.1GB,多数场景不值);MTEB看Retrieval子栏不看总分,且榜会被刷——信你自己那20个问题;微调要1000条以上真实"问题→文档"数据,用的就是推荐算法双塔那套对比学习+in-batch负采样+温度系数;🚨换embedding必须全库重建索引,灰度要双索引并行。RAGAS四指标:faithfulness(在编)/answer_relevancy(跑题)/context_precision(捞到了但埋在噪声里→加重排)/context_recall(压根没捞到→改切分和检索)——⭐先看context_recall,⚠️两个别搞反,处方完全不同;分数是LLM打的,只能当趋势指标。🚨四个指标一个都发现不了权限越权(内容相关、答案忠实、引用属实,全绿)——合规只能靠权限测试用例,⭐指标体系只会告诉你它被设计来测的东西。进阶方向各有代价:GraphRAG(建图要全库过一遍LLM,索引成本高一到两个数量级且难增量维护)/Agentic RAG(多轮,必须有步数上限)/Self-RAG(把判断力训进模型,要微调)/CRAG(把判断力放在模型外面,差就回退网络搜索)——⭐先做CRAG,不动模型加个阈值就能上。实用价值第一,见效最快。
下一节 👉 09-推理范式.md