Appearance
14.1.5 召回到了不等于模型就能答好,为什么?
先给结论:召回只是“找到候选材料”,不是“形成可回答上下文”。答案质量还取决于证据组织、上下文边界和生成约束。
这是 RAG 里一个非常容易被忽略、但实际影响极大的问题。
很多人会这样理解链路:
- 把文档放进知识库
- 把相关内容召回出来
- 让模型基于这些内容回答
听起来完全合理。但真正的问题在第 2 步和第 3 步之间:
召回出来的东西,未必已经是模型可以稳定利用的“回答证据”。
召回解决的是“有没有”,不是“怎么用”
检索阶段做的事,本质上是从大量内容里找候选。
而模型生成答案时,需要的不是一堆候选,而是一组边界清楚、关系清楚、足以支持结论的证据。
所以即使“正确片段已经被召回”,仍然可能答不好。常见原因有:
- 多段证据彼此冲突
- 证据顺序混乱,主次不清
- 关键信息埋在长文本里,不够突出
- 片段虽然相关,但组合起来仍然缺关键条件
哪些场景里最容易出现这种问题
1. 召回命中了正确段落,但上下文顺序混乱
模型看到的材料是对的,但没有被组织成一个容易理解的结构。
结果就是它抓住了一部分信息,却漏掉了真正关键的限制条件。
2. 召回同时带回了多份互相冲突的证据
例如旧版文档和新版文档同时进入上下文。
这时模型不是天然知道该信谁,它可能会混合两者,生成一个表面流畅、实则错误的答案。
3. 召回内容过长,注意力被稀释
候选材料很多,但真正与问题直接相关的只占一小部分。
模型可能读到了很多背景说明,却没有抓住你最需要的那一段。
4. 多段证据需要被拼接成完整链条
有些问题本来就不是一段能答完的。
例如一段说明功能定义,另一段说明权限限制,再另一段说明异常情况。
如果这些内容只是松散地放在一起,模型并不一定会自动拼成稳定的答案链。
所以,真正要做的是“证据组织”
把召回升级成“可回答上下文”,通常要做四件事:
1. 去重
避免同类内容反复出现,浪费上下文预算。
2. 合并
把同一主题、同一对象、同一流程下的证据尽量放在一起。
3. 标记
为每段证据保留来源、时间、版本、权限范围等信息,方便模型区分。
4. 约束
提示模型只能基于证据回答,证据不足时直接说明不足,而不是硬猜。
一个简单示意
python
context = []
for doc in reranked_docs[:4]:
context.append(
f"source={doc.metadata.get('source')}\n"
f"updated_at={doc.metadata.get('updated_at')}\n"
f"{doc.page_content}"
)
prompt = f"""
请仅基于以下证据回答。
如果证据不足,请明确说明缺少什么。
{chr(10).join(context)}
"""这段代码最重要的不是写法,而是思路:
不要把检索结果原样裸传给模型,而要把它整理成带来源、带边界、带约束的可回答上下文。
怎么判断问题在“召回”还是在“生成”
一个非常实用的方法是:
- 如果人工看检索结果都觉得证据不够,那问题在召回
- 如果人工看检索结果已经足够,但模型仍然漏条件、乱归纳,那问题通常在上下文组织或生成约束
这一步判断非常关键。
很多所谓“模型答不好”的问题,实际上是系统把未经整理的候选材料直接丢给了模型。
一句话总结
召回到了,只代表“材料到位”;答得好,取决于你有没有把这些材料组织成真正可回答的证据上下文。