用户说「答非所问」,你怎么归因是检索问题还是生成问题?
谁在问:二三面·追问重灾区;本章最能拉开差距的一题
口语化问法
- 上线后用户投诉答得不对,你从哪开始查?
- 怎么判断是没检索到,还是检索到了但模型没答好?
- 给你一个 badcase,说说你的排查流程。
考察意图
这是整个 RAG 章最能区分「做过系统」和「读过教程」的一题。 读过教程的人知道每个组件是什么;做过系统的人知道出了问题该按什么顺序拆。面试官在看三件事:① 你有没有一个确定的第一动作(而不是「先看看日志」这种废话);② 你的排查是否有序、是否收敛;③ 你会不会在没有证据前就动手调参。
参考答案
60 分答案(及格线)
第一步是把检索和生成切开:取出这次实际检索到的 chunk 看一眼——
- 如果正确答案根本不在检索结果里 → 检索的锅,去查分块、embedding、混合检索、rerank。
- 如果正确答案在检索结果里但模型没答对 → 生成的锅,去查 prompt、上下文组装顺序、模型能力。
最直接的验证方法是:把正确的文档手工塞进 prompt 再问一次。答对了就是检索问题,还答错就是生成问题。这一刀成本极低,能立刻把问题范围缩小一半。
90 分答案(有生产经验的回答)
在这一刀之后,给出完整的分层排查树:
【第 0 步】复现 + 看实际检索结果(不看日志的排查都是猜) 【第 1 刀】手工塞正确文档 → 还答错吗? ├─ 答对了 ──────────────► 检索侧问题,继续往下切 └─ 还是错 ──────────────► 生成侧问题,跳到第 3 步 【第 2 步】检索侧再分三层 ├─ 正确 chunk 根本不在候选里(recall 失败) │ ├─ 知识库里压根没有这条 → 数据缺失,不是技术问题 │ ├─ chunk 被切碎/语义断裂 → 分块问题(Q2-03/04) │ ├─ 是型号/编号类精确查询 → BM25 缺失或分词切碎(Q2-09) │ └─ 是口语化/多轮指代 → 查询改写缺失(Q2-13) ├─ 在候选里但排名靠后被截断 → 排序问题,加/调 rerank(Q2-11) └─ 被元数据过滤误杀(权限、时间)→ 过滤逻辑问题 【第 3 步】生成侧再分三层 ├─ 材料够但答偏 → prompt 指令不清、缺少「只依据材料」的约束 ├─ 材料多而杂 → 上下文太长导致失焦(context rot),减 top-k 或加 rerank ├─ 材料在中间被忽略 → 上下文顺序问题(lost in the middle),把最相关的放首尾 └─ 材料不足却硬答 → 缺少「不知道就说不知道」的约束与检索分数阈值 【第 4 步】归类打标 → 统计量级 → 按量排优先级 → 改一个变量 → 全量回归 → 加进回归集
三条纪律(这部分最能体现成熟度):
- 不看实际检索结果就不动手。 没有证据的调参是玄学,改完效果变了也不知道为什么。
- 一次只改一个变量。 同时换 embedding 又改 chunk 大小,收益无法归因。
- 单个 badcase 不驱动架构决策。 一个 case 修完要看它属于哪一类、这一类占多少量——为一个孤例上 GraphRAG 是典型的过度反应。
还要补一个反直觉的可能:用户说「答非所问」,有时问题既不在检索也不在生成,而在用户预期——他问的是「这个功能怎么用」,期待的是操作步骤,而知识库里只有功能定义。这属于知识库覆盖度问题,解法是补内容,不是调技术参数。能想到这一层,说明有产品视角。
追问链
不问「有哪些原因」,只问「按什么顺序拆、有没有证据就动手」
正确 chunk 在候选里但排在第 15 位,你怎么修?
期望这是排序问题不是召回问题:加 rerank 最直接 → 调融合参数(RRF 的k或加权α)→ 查这类 query 是不是该加重 BM25。不该做的是加大 top-k 硬塞,那会引入噪音、加剧失焦信号能把「召回问题」和「排序问题」对应到不同解法 → 框架清晰手工塞了正确文档模型还是答错,接下来查什么?
期望按顺序:① prompt 有没有明确要求「只依据材料回答」;② 材料在上下文里的位置(中间位置利用率低);③ 材料是不是太长太杂;④ 是不是模型能力不够(换更强模型只是诊断手段,不是解法);⑤ 是不是问题本身要多跳推理,而材料只覆盖了一跳信号给的是有序清单而不是「调一调 prompt 试试」→ 有方法论怎么区分「知识库里没有」和「检索没找到」?
期望直接在原始文档里全文搜关键词(或人工翻)。这一步经常被跳过,但它能立刻把「数据缺失」这类非技术问题摘出去 —— 否则你会花一周优化检索,去找一个根本不存在的答案信号想得到这个动作 → 排查过真实线上问题;想不到 → 会在错误方向上耗掉大量时间怎么把这些排查沉淀成可复用的东西?
期望badcase 打标分类(分块 / 召回 / 排序 / 生成 / 数据缺失 / 预期错位)→ 统计各类占比 → 按量级排优先级 → 每类留典型 case 进回归集 → 定期回看分布变化。回归集只增不减;进阶做成半自动脚本,自动记录检索结果、自动跑「塞正确文档」对照实验信号说得出「统计各类占比再排优先级」→ 数据驱动;只说「记录下来」→ 偏弱老板明天要看改善,你只有一天,怎么排优先级?
期望不做大改造:① 抽 20–30 个 badcase 快速归因打标,看哪一类占比最大 → ② 挑「改动最小、覆盖面最大」的一项动手(加 rerank、调 top-k、补分词词典、加「不知道就说不知道」的约束,都是小时级)→ ③ 跑回归确认没打坏别的 → ④ 汇报给分类统计 + 修了哪类 + 剩下哪类要更长周期,别拍胸脯说都修好了信号一天之内张口重建索引或上 GraphRAG → 没有工期判断;先归因统计再挑性价比最高的一刀 → 成熟工程师
本章最能拉开差距的一题,分水岭在第 3 层和第 5 层:一个考「你想不想得到先去原始文档搜一遍」,一个考一天工期里的取舍;中间两层考排查有没有序。
评分要点
- 第一动作明确:把检索和生成切开(手工塞正确文档做对照)
- 检索侧能再分层(召回失败 / 排序靠后 / 过滤误杀)
- 生成侧能再分层(指令不清 / 材料过长 / 位置靠中 / 材料不足硬答)
- 能区分「知识库没有」与「检索没找到」并给出验证动作
- 有「一次只改一个变量」的纪律
- 加分:不为单个 badcase 做架构决策,先看类别量级
- 加分:badcase 沉淀进回归集
- 加分:能想到「用户预期错位」这类非技术根因
常见错误
「先看看日志」——没有具体的第一动作,等于没有排查框架。
直接开始猜「可能是 chunk 切得不好」,不做任何对照实验就动手调参。
检索和生成混在一起排查,改了一堆东西说不清哪个起了作用。
一个 badcase 就要上 GraphRAG / 换大模型——过度反应。
修完就完了,不分类、不统计、不进回归集。
从没想过「知识库里可能压根没这个答案」。