登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

RAG 检索结果明明相关却答非所问:如何定位召回、切片与上下文拼接问题

来源:17golang原创

时间:2026-08-26 17:52:36 309浏览 收藏

知识库里明明有答案,检索接口返回的几段文字也和问题相关,最终回复却把两个版本的规则拼在一起,甚至漏掉了真正的限制条件。RAG 遇到这种情况,先别急着换模型;把“召回了什么、排序后留下什么、送进上下文什么”逐段摊开,通常能在十几分钟内找到丢失点。

要点速览
  • 先保存 query、chunk_id、score、rank 和最终 prompt,别只看模型最后一句话。
  • 召回相关不等于上下文可用,切片边界和相邻段缺失会改变规则含义。
  • 同一问题同时命中旧版与新版资料时,必须显式处理版本、时间和来源优先级。
  • 修复后用固定问题集复测召回覆盖率、引用准确率和拒答边界。

先把一次错误回答拆成四份证据

排查时我会给每次请求分配一个 trace_id,同时记录问题内容、检索参数、候选片段和最终上下文。这样能区分“没搜到”“搜到了但被截掉”和“上下文正确但模型误读”三类故障。

{
  "trace_id": "rag-20260826-0042",
  "query": "试用期内申请远程办公需要谁审批?",
  "retrieval": [
    {"chunk_id": "hr-2025-14", "score": 0.82, "rank": 1},
    {"chunk_id": "hr-2024-09", "score": 0.79, "rank": 2}
  ],
  "context_chunk_ids": ["hr-2025-14"],
  "answer": "需要直属经理和人事共同审批。"
}

这个例子里,第二段虽然被召回,却没有进入上下文。若新版制度只要求直属经理审批,答案里的“人事共同审批”就可能来自旧片段,而不是模型凭空编造。

RAG 检索证据链:用户问题经过召回、排序后只保留一个上下文片段,旧版本片段被标记为风险

召回相关,为什么仍然可能排错顺序

向量相似度只回答“文字像不像”,不负责判断哪一条制度更新、哪一条适用于当前部门。尤其当知识库里同时存在“2024 年员工手册”和“2025 年补充规定”时,两个 chunk 都可能排在前几位。

先把同一问题的 top-k 结果原样打印出来,至少观察四个字段:来源文档、发布日期、适用范围和命中的句子。不要只记录一个浮点分数,否则后面无法解释排序为何改变。

检查字段要问的问题异常信号
chunk_id是否来自同一份文档的连续片段相邻段被打散,规则缺半句
source_version是否存在新旧版本同时命中旧版 rank 更高
scope是否适用于当前角色或地区部门条件被忽略
score/rank排序是否被相似但无关词干扰关键词相同但结论不同

如果排序分数相近,建议把版本和适用范围作为二次排序字段,而不是继续把 top-k 从 5 调到 20。候选越多,冲突资料进入上下文的概率也会增加。

切片边界如何把一句限制条件切没

很多“答非所问”不是召回失败,而是切片刚好从条件句中间断开。例如原文是“试用期员工仅限紧急情况申请,须由直属经理审批”,切片一只保留了后半句,模型自然会把普通申请也当成允许项。

用固定问题检查每个 chunk 是否自洽:单独拿出片段,读者能否知道它的主语、时间范围、例外条件和动作对象?若不能,就需要调整切片策略。实践中可以先按标题、段落和列表项切分,再设置小范围 overlap;不要把 overlap 当作补救所有语义断裂的万能开关。

for chunk in chunks:
    assert chunk["text"].strip()
    assert chunk["metadata"].get("source_version")
    assert chunk["metadata"].get("section")
    # 检查片段是否带有条件、例外或适用范围
    check_boundary(chunk["text"])
RAG 上下文拼接检查:完整制度段落经过切片后,版本与例外条件被保留并进入最终上下文

最终上下文里最容易发生的三种丢失

把检索结果送给模型前,通常还会经历去重、重排、长度截断和模板拼接。这里至少要检查三次:排序后的候选列表、截断后的 chunk 列表、最终 prompt 中实际出现的文本。三者只要有一个不一致,单看向量库日志就会误判。

  • 去重过早:以标题或来源名去重,导致同文档里真正补充条件的段落被删掉。
  • 长度截断:按字符数从尾部裁剪,把例外条款或引用来源裁掉。
  • 模板覆盖:系统提示要求“优先使用上下文”,但后面的历史对话又带入了旧结论。

修复时不要只增加上下文窗口。先在日志中展示最终发送的 chunk_id,并给每段上下文加上来源、版本和章节标记。模型看到“2025 补充规定 / 远程办公 / 试用期”这样的边界信息,才有机会做出可解释判断。

用一组固定问题证明修复真的生效

建立十到二十条小型回归集即可,不必一开始追求大而全。每条问题至少带一个标准答案要点、一个必须引用的来源和一个容易混淆的旧版本。修复前后分别记录召回覆盖率、正确来源命中率、答案中的冲突条款数。

其中“冲突条款数”很有用:如果回答看起来更长,但同时引用了新旧两套规则,不能算修复成功。对不在知识库的问题,还要保留拒答样例,防止为了提高命中率而放宽回答边界。

常见问题

把 top-k 从 5 调到 20 能解决答非所问吗?

不一定。它可能提高召回覆盖,却也会把相互冲突的版本一起送进上下文。先检查排序、版本和切片完整性,再决定是否扩大候选范围。

向量相似度高,就能说明片段适合回答吗?

不能。相似度主要反映文本接近程度,适用部门、日期、版本和例外条件仍需要元数据或二次排序参与。

如何判断是模型问题还是 RAG 链路问题?

固定最终上下文,用同一个模型重复测试;再把正确片段直接放入上下文做对照。如果直接上下文能答对,而完整链路答错,优先检查召回、重排或拼接。

把排查结果留下来,下一次才不用猜

一条可复用的 RAG 诊断记录,应能从 trace_id 还原 query、top-k、版本和最终 chunk_id,并能用固定问题集复现修复前后的差异。模型只是最后一个环节;把前面的证据链补齐,很多“玄学回答”会变成具体的排序、切片或上下文边界问题。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>