🏠 总目录📚 本教程 08 · RAG 深水区
📑 本页目录(点开跳转)

08 · RAG 深水区

76 分钟 | ⭐⭐⭐ 落地场景最多的一块


🎯 一句话

RAG 的 demo 版本一小时能搭出来,生产版本能做三个月。差距不在「向量检索」这四个字,而在切分、混合检索、重排、查询改写、评估这一整条链路。 而这条链路上最容易被搞反的是顺序:先做切分和混合检索,再加重排,最后才轮到换 embedding 模型

用户问题向量化同一个嵌入模型向量库检索取 top-K 相似块重排 Rerank精排一次拼进提示词问题 + 检索到的块模型生成带引用文档库离线切块+嵌入RAG 不是「让模型记住文档」,是「每次把相关的那几段塞给它」所以效果的上限,几乎完全由【检索准不准】决定,而不是模型多强⭐ 排查 RAG 效果差,永远先看「检索回来的块对不对」——而不是先去换更大的模型
蓝色是检索链路,橙色是生成链路。⭐ RAG 的效果上限几乎完全由「检索准不准」决定 —— 所以排查效果差时,永远先看检索回来的块对不对,而不是先换更大的模型。

😅 先看差距有多大

   【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。 这一节回答的是"轮到了之后怎么选",不是"一上来先选哪个"

什么时候是真的该换了

信号 说明
语种不对 拿纯英文模型跑中文——这不是"效果差一点",是根本不该出现的配置错误。中文/多语言场景先确认模型的训练语料覆盖
领域词汇完全在分布外 医学、法律、化学式、内部工单代号。通用模型没见过这些词,它们的向量互相挤在一起,怎么调都分不开
⚠️ 文本长度对不上 模型 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 榜怎么看(榜首≠对你最好)

  1. 看子任务,不看总分。 MTEB 总分把分类、聚类、语义相似度、检索混在一起平均。你只关心 Retrieval 那一栏;中文看 C-MTEB 的检索子集。
  2. 顺手看"参数量"和"维度"两列。 榜首常是 7B 级的 embedding 模型——它的推理成本可能比你整条检索链路还高。
  3. ⚠️ 榜单会被刷。 训练数据里混进评测集是这个榜公开的老问题。一个模型只在榜上好、在你那 20 个问题上不好,信你自己的。
  4. 别忘了迁移成本:换 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_precisioncontext_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 上等于开局领先半场——那一套搜索/排序知识至少一半可以直接用没做过也别绕路:上表右列就是你要学的东西本身,只是别人已经在另一个领域学过一遍而已。


📦 深挖的话要学什么

✅ = 本章正文已经讲了,点进去就是;其余是本章之外的。

📍 本章之外的那些,也标了它在哪: 📗 本库有 = 站内已经讲透,点进去就行;📙 半有 = 站内讲了一半,另一半得外找; 📕 要外找 = 站内没有,得去论文或别处。 (这份清单以前只列词不说去哪,指到的坑有些站内根本没挖过,按图索骥会扑空。)

需要的前置:不需要 GPU、不需要新数学,会调 API 就能开始。⭐ 做过推荐/搜索或写过 Agent 的人几乎是零前置(站内《推荐算法》《智能体工程教程》覆盖的就是这两块);没有这些背景的人,前置也只是「会用向量数据库存取一次数据」。


⚖️ 要不要深挖

你的情况 建议
要做企业知识库/客服/文档问答 必须,且优先级最高
做任何需要「模型用上私有数据」的事 ✅ 必须(比微调重要得多)
只做通用对话应用 🟡 知道基础即可
想快速产出可用成果 这块见效最快

🔑 我的判断:如果只能深挖一块,从纯实用角度这块排第一: - 落地场景最多(企业知识库是当前最主流的 AI 落地形态) - 迁移余地最大(做过推荐/搜索的话,那套知识直接复用;没做过也是全表门槛最低的几块之一) - 见效最快(一周能做出可用的东西) - 不需要 GPU、不需要新数学

唯一的竞争者是第 2 章 Transformer 原理——那个是认知价值最高,这个是实用价值最高。


✅ 检查点

  1. RAG 的漏斗结构和推荐系统的什么结构对应?
  2. 块太大为什么反而检索不准?(说出机制)
  3. 高维向量的什么性质决定了「只调 embedding 模型救不回来」?该配什么?
  4. 为什么必须用混合检索而不能只用向量?
  5. 上下文检索(Contextual Retrieval)做了什么?效果如何?
  6. 为什么说重排是性价比最高的一步?
  7. RAG 答案不对,第一步该查什么?最有价值的排查习惯是什么?
  8. 「召回里有正确文档但答案还是错」——该查什么?
  9. HyDE 的原理是什么?
  10. Cross-Encoder、ColBERT、LLM 重排三条路线的核心差别是什么?默认该选哪个、为什么不该从 ColBERT 开始?
  11. ColBERT 的 MaxSim 是怎么算的?它换来了什么、代价是什么?
  12. 什么信号说明"该换 embedding 模型了"?换模型有一条什么运维铁律?
  13. RAGAS 的四个指标分别问什么?context_precision 低和 context_recall 低,处方有什么不同?
  14. 为什么说 RAGAS 分数只能当"趋势指标"?
  15. 诊断表里哪一类问题是四个指标一个都不会亮的?该怎么查?
  16. Self-RAG 和 CRAG 在解决同一件什么事?两者的区别是什么?工程上先做哪个?
👀 答案
  1. 召回→粗排→精排→重排。RAG 本质是一个搜索系统。
  2. 一个块的 embedding 是它整体语义的平均。塞进三个主题,向量就落在三者中间的"没人区",对哪个主题的问题都不够近
  3. 维度灾难——500 维时最远和最近的点距离只差 19%,「最近邻」这个概念本身在变弱。所以必须配 BM25(字面匹配不受影响)和重排(Cross-Encoder 不依赖向量距离)。
  4. 向量懂语义但对精确的专有名词/型号/代码不准(可能召回 XR-3000 而不是 XR-2000);BM25 精确匹配但不懂同义。两路融合(RRF,只用排名不用分数)互补。
  5. 给每个分块补一句"它在讲什么"的上下文说明再向量化,让孤立的块也能被检索到。官方数据检索失败率降约 49%
  6. 双塔检索快但不能深度交互;Cross-Encoder 把问题和文档拼一起过模型,准得多。在已召回的几十条上重排,成本可控而收益大,通常比换 embedding 模型更划算
  7. 先查检索——正确文档有没有被召回。最有价值的习惯:每次答错都把召回的原始块打印出来看一眼,十次里七次问题不在生成侧。
  8. 查它排第几——大概率是重排缺失,正确文档排在第 15 位被截断了。
  9. 先让模型假装回答生成一个"假答案",用假答案去检索。因为假答案和真文档的表述风格更接近,比原始问题更容易匹配上。
  10. 核心差别是问题和文档在什么时候相遇:Cross-Encoder 最早(拼一起过模型,文档一条都不能预计算,最准也最慢);ColBERT 在中间(各自编成 token 级向量,查询时才 MaxSim,文档侧可离线);LLM 重排是"读懂了再排"(秒级 + token 账单)。默认 Cross-Encoder。不该从 ColBERT 开始是因为它解决的是规模问题不是效果问题——拿它替代 Cross-Encoder 通常是效果的降级。
  11. 每个问题 token,取它和所有文档 token 里最像的那个的相似度,全部加起来。换来的是文档那几百个向量可以离线算好,在线只剩点积,比 Cross-Encoder 快一到两个数量级。代价是存储爆炸:一个块从 1 个向量变成几百个向量,索引体积膨胀一个数量级(ColBERTv2 用残差压缩压回来一些)。
  12. 四个信号:语种不对(英文模型跑中文是配置错误不是效果问题)、领域词汇完全在分布外(医学/法律/工单代号)、⚠️块长超过模型 max_seq_len 被静默截断(最隐蔽,因为不报错)、非对称检索没加 query/document 前缀。铁律:换 embedding 必须全库重建索引——新旧向量空间不通用,混在一个索引里检索结果会乱且不报错;灰度期要双索引并行
  13. faithfulness 答案有没有依据(模型在编)、answer_relevancy 答没答这个问题、context_precision 有用的排没排在前面、context_recall 需要的信息捞没捞到。recall 低 = 没捞到 → 改切分和检索;precision 低 = 捞到了但埋在噪声里 → 加重排。 处方完全不同,认错就一直修错的那一环。
  14. 因为这四个分数多数是 LLM 打出来的,自带 LLM-as-a-Judge 的毛病:随裁判模型版本漂移、按 token 计费、同一批数据两次跑结果不完全一样。所以「我们的 faithfulness 是 0.87」离开裁判模型和版本就没有意义,只能比"这次改动比上次高了吗"
  15. 权限越权(别人的数据被查出来)。被越权召回的文档内容相关、答案忠实、引用属实,四项全绿。只能靠专门的权限测试用例——拿 A 用户的身份去问只有 B 能看的问题,断言召回为空。通用教训:指标体系只会告诉你它被设计来测的东西。
  16. 都在给 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

打卡记录保存在你的浏览器里,首页能看到总进度