目录
1.常见指标:
1.1指标之间区别
疑问一
例子
2.badcase分析
2.1 回答与问题高度相关,但事实错误。
2.2正确答案在库里但没进 top5
2.3 rag中用户提问一直检索不到正确的内容你怎么进行排查
在项目的评测阶段,badcase 分析往往是项目调优的关键环节。
1.常见指标:
context_precision上下文精确度:检索出来的片段里,正真和问题相关的占比;低=检索的噪声大,混入很多无关的文档块
context_recall上下文召回率:知识库中正真相关的片段,有没有被检索出来;低:相关问题答案没有找全
faithfulness忠诚度:大模型回答是否严格依据检索到的上下文,不变编造信息;低=模型幻觉在编瞎话
response relevancy回答相关性: 生成的答案是否贴切用户问题
Answer Correctness正确性/相似度:当你有参考答案(ground truth)时可用;没有参考答案时通常以 Faithfulness/Context 相关指标为主。
1.1指标之间区别
1.1.1召回率和精确度定义上的区别:
都是比较rag检索出来的上下文质量但是其中:
Context Recall(上下文召回率):以标准答案为参照,看标准答案里的知识点被召回了多少。
Context Precision(上下文精确度):以检索结果为参照,看检索出来的 Chunk 有多少是相关的,以及相关 Chunk 的排名。
Recall 关注有没有漏掉重要知识,Precision 关注召回结果中有多少有效信息,以及排序是否合理。Recall 和 Precision 确实都关注有效信息,但它们统计的对象不一样。
疑问一
假设你的项目中,用户提问:
A-100 产品安装需要哪些步骤?
知识库中的标准答案有 6 个步骤:
情况一:只召回一个 Chunk
检索结果:
retrieved_contexts = [ "步骤1:检查设备;步骤2:安装底座;步骤3:连接电源" ]此时:
Context Recall = 3 / 6 = 0.5
因为标准答案有 6 条,但只找到了 3 条。
Context Precision = 1.0
因为检索出来的唯一一个 Chunk 是相关的,而且排在第一名。
发现了吗?
虽然只找回了三个知识点,但是检索出来的内容没有无关信息。
所以 Recall 低,Precision 高。
情况二:召回两个 Chunk
retrieved_contexts = [ "步骤1、2、3", "步骤4、5、6" ]此时:
Context Recall = 6 / 6 = 1.0
Context Precision = 1.0
既没有遗漏知识点,也没有无关 Chunk。
情况三:召回三个 Chunk
retrieved_contexts = [ "步骤1、2、3", "A-100产品品牌发展历史", "步骤4、5、6" ]此时:
Context Recall = 1.0
因为 6 个知识点全部召回了。
但是 Context Precision 会下降,因为第二个 Chunk 与用户的问题无关。
按照 RAGAS 常用的排名加权精确度公式计算:
这里的数值是按简化的人工相关性标签计算的,实际 RAGAS 还需要模型判断相关性。
所以一句话总结:
Context Recall 解决的是“找得全不全”,Context Precision 解决的是“找得准不准、排得好不好”。
在 RAG Bad Case 分析中,前者主要帮助发现知识遗漏,后者主要帮助发现无关召回和排序质量问题。
例子
情况一:Precision 高,但 Recall 低
假设检索只返回三个 Chunk:
检索排名 | Chunk 内容 | 是否相关 |
|---|---|---|
Top1 | 关闭仪表电源 | 相关 |
Top2 | 断开测试表笔 | 相关 |
Top3 | 断开被测电路 | 相关 |
此时:
Context Precision 很高:三个 Chunk 都相关,而且都排在前面。
Context Recall 较低:标准答案有 6 个知识点,却只召回了 3 个。
情况二:Recall 高,但 Precision 低
假设检索返回六个 Chunk:
检索排名 | Chunk 内容 | 是否相关 |
|---|---|---|
Top1 | 万用表的发展历史 | 无关 |
Top2 | 安全事项 1、2 | 相关 |
Top3 | 万用表产品介绍 | 无关 |
Top4 | 安全事项 3、4 | 相关 |
Top5 | 万用表品牌信息 | 无关 |
Top6 | 安全事项 5、6 | 相关 |
此时:
Context Recall 很高:6 个知识点全部召回了。
Context Precision 较低:存在大量无关 Chunk,并且相关 Chunk 排名靠后。
这说明系统并没有漏召回知识,但是检索质量和排序仍然需要优化。
评测结果 | 说明什么问题 | 优化方向 |
|---|---|---|
Recall 低,Precision 高 | 召回的内容很相关,但知识不完整 | 扩大召回 TopK、优化 Chunk 切分、补充多路召回 |
Recall 高,Precision 低 | 知识比较完整,但夹杂无关 Chunk,排序不佳 | 优化 RRF 融合、Rerank 重排序 |
两者都低 | 知识既不完整,相关性也差 | 排查实体过滤、Embedding、文档入库和检索策略 |
两者都高 | 检索阶段整体较好 | 继续检查 LLM 生成质量 |
2.badcase分析
2.1 回答与问题高度相关,但事实错误。
用户提问 A型号的万用表测的最大电压是多少?假设正确的答案是600v,但是模型回答的是1000v
Faithfulness(忠实度):低- 上下文相关性(Context Relevance,也常和 Context Precision 挂钩):高
- 因为ragas是这样进行计算的:根据模型的回答,反向生成问题,在比较这些问题和原始问题的相关程度
一、先判断错误发生在哪个阶段
存在两种情况:
检索文档写着600V,但是模型回答600V -----》生成阶段出现幻觉
检索到B型号,上面写着1000V -----》检索阶段召回错误
二、解决
1. 如果是检索正确但是模型回答错误:
说明模型没有严格遵循检索上下文,可以通过提示词约束,添加COT思维链,增加结构 化字段对比,来源引用和结果效验,将大模型的temperature降低等方法降低模型输出错误 的概率
2.如果检索到了错误的文档
这个时候需要优化检索链路,进行ragas测试,再结合其他指标进行判断或者结合日志
文件找到错误的位置(因为检索出来的语义比较相近A-100或A-200,所以单纯提高TopK或增
加向量检索的数量,并不能从根本上解决问题 TOP1: A-200 TOP2:A-100)
2.1 解决问题
1.商品名识别确认用户问的是谁,将用户的自然语言解析成结构化语句,提取商品名,
再和milivus商品实体匹配,将商品映射成唯一的product_id,将这个id放在切片chunk中一起向
量化
2.添加标量过滤条件,dense 和 sparse 混合检索;rrf + rerank,把正确文档排到前面。但 rrf 和 rerank 只能做排序,不能解决所有召回问题
2.1.2 但优化之后还要召回不到正确答案怎么办?
这种情况往往在知识入库阶段排查,调整文档切分策略,可以把 chunk 变成结构化语句{"product_id":"...","title":"...","text":"..."}
2.1.3 还可以添加 “跨物品误召回率”:单次检索结果中错误商品 chunk 所占比例。
此外还可以记录各阶段 TopK 结果,区分正确知识没有入库、正确知识没被召回和正确知识被召回但被排序淘汰。
2.1.4正确知识没有入库:
思路 ① 检查原始 PDF 是否包含正确知识
② 检查 minerU 解析的 markdown 是否完整
③ 检查文档切分时候有没有丢失 / 拆散参数
④ 检查 Embedding 和 milvus 入库是否成功
⑤ 检查 chunk 的 product_id,是否正确
2.1.5 知识已经入库,但没有召回?
①先检查商品标量过滤是否错误,然后再看正确文档在各路检索的排名
检索方式: Dense Top18
Sparse Top2
HYDE Top8
可以增加候选数量,调整 Dense/Sparse 比例 以及改写 query 改写。 例如将 Dense 单 检 limit 提到 20, 但 TopK 只是扩大范围,会增加开销和噪声 需要用评测数据集验证。
2.1.6 正确知识召回了,但排序淘汰了
同一个 chunk 在各阶段排名变化
Sparse 召回 → rrf 融合 → rerank
2 4 8 被 top5 淘汰
解决:chunk 的文本缺少商品名,章节标题等
重排序模型对产品参数类数据识别效果不好
Rerank 输入的 Query 丢失了关键商品型号。
候选文档存在大量相似内容。 可根据原因尝试补充 chunk 标题,优化重排序输入,调整 rerank 模型,以及进阶扩大最终 TopK。
2.2正确答案在库里但没进 top5
第 1 层:查询层(你刚说的,最表层)
① 每路口 limit:5 → 20/50,放大召回池
② 融合后 topk:同步放大(hybrid_search limit)
③ 权重:看语义路/词级路哪个更适合业务,比如 (0.7, 0.3)
第 2 层:下游截断层
就算 Milvus 返回了 10 条,后面还有三道闸门可能把正确答案砍掉:
混合检索 limit=5 → RRF [:10] → reranker 断崖(差值≥0.5) → 答案节点 2000字符
- RRF 截断:如果多路召回,看正确答案在 RRF 融合后第几名,[:10] 会不会砍掉它;
- reranker 断崖:正确答案向量分数不高但内容其实相关,reranker 可能给它低分,又被断崖检测切掉——这时要查 reranker 打分结果,调 0.5 阈值或修 cliff 逻辑;
- 2000 字符:排前面但太靠后,拼提示词时被字符上限截断。
第 3 层:上游数据层(根本原因,面试加分点)
① 切分粒度:切片太长(语义被稀释)/太短(语境丢失)→ 调整 2000/500 的切分参数
② 向量化质量:embedding 模型和业务语料是否匹配(BGE-M3 对中文产品文档效果好不好,可换模型/微调)
③ 向量化输入:项目里 embed_content = item_name + "\n" + content —— 加了商品名前缀就是为了增强召回
④ 标量过滤误伤:expr = item_name in [...] —— 商品名识别错了,正确答案所在的切片直接被过滤掉,
根本没进检索!这种情况调 limit 一万次也没用
⑤ 查询侧:rewritten_query 写得不好 → 优化重写提示词
第 4 层:检索策略层(项目已内置的补救)
① HyDE 假设文档检索——就是为"查询和文档词汇不匹配"准备的第二路(你向量路 miss,HyDE 路可能 hit)
② 多路召回 + RRF——单路漏了,另一路补上
三、面试推荐话术
"我会先定位问题出在哪一层,而不是直接调参数。第一步看这条正确答案的切片在不在召回候选里——如果压根没被检索到,先查是不是标量过滤把它挡了,再查向量化质量(embedding 输入、切分粒度);如果在候选里但排名低,就放大每路口 limit、调整融合权重;如果进了候选也被截断,就查下游的 RRF 截断和 reranker 断崖。参数层面 limit 是召回旋钮、权重是排序旋钮,两者作用不同。另外项目里我们有多路检索加 HyDE 兜底,单路 miss 还有第二路补。"
2.3rag中用户提问一直检索不到正确的内容你怎么进行排查
一、排查框架(先定性,再逐层)
第一步:定性 —— 个别问题,还是所有问题都检索不到?
├─ 个别 query 失败 → 大概率数据/过滤/改写问题(针对这条查)
└─ 普遍失败 → 大概率切分/向量化/embedding 模型问题(系统性)
│
第二步:逐层排查(顺着检索链路从入口到出口)
│
第三步:对照实验定位(构造标准问法测试)
│
第四步:对症修复
二、结合项目的逐层排查清单
顺着我们项目的链路一层层查:
用户问题 → 商品名确认 → 三路检索 → RRF → reranker → 答案生成
| 层 | 排查问题 | 项目排查手段 |
|---|---|---|
| ① 商品名确认 | 商品名提取对了吗?重写问题对吗? | 看日志里 LLM 返回的 item_names /rewritten_query(节点有 print) |
| ② 商品名确认 | 商品名被 0.7 阈值拒绝了吗? | 直接返回 "当前问题无法识别"= 短路了,问题在商品名库或提取 |
| ③ 标量过滤 | item_name in [...] 把正确切片挡了吗? | 检查库里正确切片的 item_name 和查询的 item_names 是否一致(商品名写错字、别名不一致都会漏) |
| ④ 检索分数 | 正确切片的相似度分数是多少?排第几名? | 单独把正确切片向量化算相似度 —— 分数低 = 向量化 / 改写问题,分数高但没进 top5 = 截断问题 |
| ⑤ 数据入库 | 正确文档真的入库了吗? | 查 chunks.json 备份、Milvus 直接按主键 / 条件查这个切片在不在 |
| ⑥ 切分质量 | 正确答案被切碎 / 切混了吗? | 看切分结果:答案内容是否完整在一个切片里,还是和无关内容混在一起 |
| ⑦ 下游截断 | 进了候选但被砍掉了吗? | 查 RRF 融合后的名次、reranker 打分数、断崖切点、2000 字符截断 |
| ⑧ 模型适配 | embedding 模型适合业务语料吗? | BGE-M3 对中文产品手册的效果,必要时换模型 / 微调做对比 |
三、两个对照实验(面试加分项)
实验 1:标准问法测试(区分"查询问题"还是"数据问题")
拿一条和正确答案高度相似的"标准问法"直接检索:
├─ 能召回 → embedding 和数据没问题 → 问题在查询重写/口语化
│ (用户问法太口语,rewritten_query 质量差)
└─ 也召不回 → 问题在数据侧 → 查切分/向量化/入库
实验 2:单节点直测(项目每个节点都有 __main__)
不要跑全链路,单独测:
├─ 单测检索节点:固定 rewritten_query 和 item_names,看返回什么(隔离上游变量)
├─ 单测切分节点:喂一份已知 MD,看切片结果(隔离数据质量)
└─ 直接 milvus_client 查库:确认正确切片是否存在、向量是否正常
这两个实验的价值在于二分定位——一次排除一半可能,而不是漫无目的地调参数。
四、面试推荐话术
"我一般先定性:个别问题还是普遍问题。个别问题大概率是标量过滤或者查询改写的问题——比如商品名提取错、和库里写法不一致,正确内容被过滤条件挡在检索之外,这种情况调 topk 没用;普遍问题大概率是切分或向量化质量——比如切片把答案切碎了,或者 embedding 模型和业务语料不匹配。定位手段上我会做对照实验:拿一条和正确答案高度相似的标准问法直接检索,能召回就说明是查询侧问题,召不回就是数据侧问题;然后再逐层看,是压根没进候选、还是进了候选被 RRF 截断或 reranker 断崖砍掉。我们项目里每个节点都能单独跑、还有 chunks.json 中间备份,排查起来很方便。"
五、易错点
1. 别一上来调参数——"没进候选"和"进了被截断"的修法完全不同,先分清是召回问题还是排序问题;
2. 最容易漏的一层是标量过滤——向量分数再高,item_name in [...] 不匹配就直接出局,这是 RAG 加了过滤条件后的特有故障点;
3. "一直检索不到"要先怀疑数据侧——单个 query 失败才优先查查询侧,普遍失败时 embedding/切分/入库出问题的概率远大于参数问题。
2.4文档切分导致语义丢失时,怎么定位和优化?
先从 bad case 入手,看原文里是否有答案,再查召回结果中有没有包含关键切片。如果原文有答案但召回没有命中,重点检查切片粒度、embedding、过滤条件和 RRF;如果召回命中了但 rerank 丢掉,检查重排模型对长文本后半部分是否不敏感。优化手段包括调小 chunk、增加 overlap、保留更多 RRF 候选、提高 rerank TopK、增加标题和商品名上下文。优化后用同一批问题集复测 context_recall、context_precision 和 answer_correctness。
欢迎交流指正