RAG 召回摘要问题排查
RAG「召回老是只拿到摘要/标题」,通常不是模型问题,而是检索阶段把 chunk 做得太“轻”或索引里只有摘要字段导致的。按下面顺序排查,基本都能定位并解决:
1) 先确认:你到底把什么写进了向量库?
最常见情况:embedding 的输入用的是 summary / title,或者只把摘要字段入库了,所以召回结果当然也只像“摘要”。
- 检查 embedding 代码:embedding 的
text_to_embed是否来自摘要字段? - 检查入库字段:向量库里每条记录是否有
content_chunk(原文片段)以及doc_id / source / offset等元信息? - 快速验证:随便抽一条向量库记录,看
text/payload是否就是摘要。
修复原则:
- embedding 必须来自原文 chunk(摘要可以作为 metadata,或辅助 BM25/重排特征,但不要替代 chunk 原文)。
- 召回返回的
text应该是可直接拼进 prompt 的原文片段,不是 summary。
2) Chunk 策略:别把 chunk 做成“自动摘要”
如果你在切分时做了“每段先总结成一句话再入库”,那召回自然像摘要。
推荐做法(经验值):
- chunk size:中文 300–800 字(或 500–1500 tokens)
- overlap:10%–20%(例如 80–150 字)
- chunk 里保留:原文 + 小量结构(标题层级/小节名)
另外,务必把这些写进 metadata:
document_title / section_title / heading_pathchunk_indexsource_urlstart_char/end_char或页码
这样召回后你能“回填上下文”,不至于只靠一段话。
3) 召回时返回字段:不要只取 summary 字段
很多人 query 时只取了 summary(比如为了省 token),导致看起来“召回都是摘要”。
- 检查 query 返回:是否有
chunk_text?还是只取了summary? - 如果你做了两段式:先召回 doc,再取 doc.summary ——那你需要在第二段再召回 doc 下的 chunks,或者直接召回 chunks。
正确链路(常见可行):
- query → topK chunks(向量/BM25/混合)
- 可选:cross-encoder rerank top 50 → top 5–10
- 把 top chunks 原文拼 prompt(带来源)
4) 你看到“像摘要”,也可能是重排/压缩器在作祟
如果你用了:
- LLM-based rerank
- contextual compression(压缩检索结果)
- “回答前先总结证据”的链
这些会把 chunk 压成摘要再喂给下游。
排查方法:
- 在进入 LLM 前,打印/日志输出最终 prompt 里的“证据块”到底是什么。
- 关掉压缩器,直接把原文 chunk 喂给生成,看是否恢复。
5) 混合检索 + 重排,能显著减少“泛泛摘要”
如果你的语料结构化强、标题多,纯向量容易召回“概述性段落”。
建议:
- Hybrid:BM25(关键词) + 向量(语义)一起召回,再合并去重
- Rerank:cross-encoder(例如 bge-reranker、cohere rerank 等)对 top 50 做重排
- MMR:让 topK 更“多样”,减少都落在概述段落
6) 如果你确实需要摘要:让摘要作为“补充视图”,不是召回主体
可以在每个 chunk 或 doc 旁边存:
doc_summary(文档级)chunk_summary(可选,用于浏览/展示) 但回答时:- 证据引用:用
chunk_text - 用户展示:可以额外显示 summary 作为“预览”
如果你把你当前的链路贴一下(哪怕是伪代码也行):
- 入库时 embedding 用的字段;2) chunk 大小/overlap;3) query 返回哪些字段;4) 是否用了压缩/重排。 我可以直接指出是哪个环节把内容变成“摘要”的。