24-RAG重排改写与证据边界
RAG 怎样取得完整证据?重排、改写与拒答
正确文档进入候选,却排在很后;改写问题以后,关键订单编号消失了;上下文塞得更多,回答反而忽略例外。这些问题说明召回数量与最终证据质量不是同一件事。
Spring AI 接入片段使用 Java 17、Spring Boot 3.5.3 与 Spring AI 1.1.8;协议与第三方平台示例另行标明适用范围。
1. 重排先解决候选顺序
它不能找到根本没有进入候选的证据。
重排为什么通常放在召回之后?
Embedding 检索适合从大范围选出候选;Cross-Encoder 等重排方法可以同时读取问题与片段,进行更细的相关性判断,但逐对计算通常有更高成本。
因此常见流程是“召回较多候选,重排后选择少量证据”,而不是对全库每篇文档都调用重排模型。Sentence Transformers Retrieve & Re-Rank
相关性高仍不保证当前有效或已授权。权限、版本与来源过滤必须在内容交给外部重排服务之前完成。
重排结果也要检查协议
外部重排接口可能返回候选下标与分数。程序要检查下标范围、重复、缺失和非有限值,不能直接用返回下标访问数组。
下面 Java 17 接入组件只定义并校验接口契约,不假设某个供应商的 HTTP API。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public final class RerankStage {
public record Hit(String id, String text) {}
public record Ranked(int index, double score) {}
public interface Reranker {
List<Ranked> rank(String query, List<String> candidates);
}
private final Reranker reranker;
public RerankStage(Reranker reranker) {
this.reranker = reranker;
}
public List<Hit> choose(String query, List<Hit> authorizedHits, int keep) {
if (query == null || query.isBlank() || keep < 1 || authorizedHits.size() > 50) {
throw new IllegalArgumentException("invalid request");
}
if (authorizedHits.isEmpty()) return List.of();
List<Ranked> ranked = reranker.rank(query,
authorizedHits.stream().map(Hit::text).toList());
if (ranked == null) throw new IllegalStateException("rerank response missing");
Set<Integer> seen = new HashSet<>();
for (Ranked item : ranked) {
if (item == null || item.index() < 0 || item.index() >= authorizedHits.size()
|| !Double.isFinite(item.score()) || !seen.add(item.index())) {
throw new IllegalStateException("invalid rerank response");
}
}
List<Ranked> sorted = new ArrayList<>(ranked);
sorted.sort((a, b) -> Double.compare(b.score(), a.score()));
return sorted.stream().limit(keep).map(item -> authorizedHits.get(item.index())).toList();
}
}
示例允许服务只返回候选子集,并约定高分更相关。真实供应商的分数方向、截断和最大输入需另外确认;如果业务要求完整排序,还应检查返回是否覆盖全部候选。
它没有实现 HTTP 调用,不是可直接请求某个模型的客户端。Reranker 实现还需超时、额度与脱敏规则。
2. 改写需要保护问题里的精确信息
扩展路线增加召回机会,也增加漂移与费用。
查询改写可能改善什么?
多轮对话的“那它支持什么格式”缺少主语,可基于已授权历史补全对象。用户词语与文档术语不同,也可以增加检索表达。
改写必须保留产品、版本、编号、时间与否定条件。把“哪些不支持”改成“支持哪些”,检索即使更容易命中,也改变了原问题。
可以同时保留原问题和受控改写,并记录改写版本。生成答案仍回答原问题,不能把改写当成用户亲自补充的事实。
改写与扩展不能无限增长
生成十个改写各检索二十条,再全部送入重排,候选与费用会快速增加。要限制改写数量、每路候选、去重后总量和整体截止时间。
查询改写服务失败时可以按规则使用原问题;重排失败时可以回退到原排序,但应记录这次使用了回退方案。回退后是否仍有足够证据,要重新判断。
外部重排会接触原文,调用它本身也是数据出域的一步。不能直到最终生成前才开始检查权限。
什么是消融评估?
在其余条件固定时,比较去掉或加入某一步的结果:基线召回、基线加改写、基线加重排、两者同时加入。
| 方案 | 主要观察 |
|---|---|
| 基线 | 原始召回与完整证据覆盖 |
| 加改写 | 新候选是否带来正确证据,也是否改变意图 |
| 加重排 | 正确候选是否进入最终 Prompt |
| 两者 | 收益是否叠加,额外延迟与费用是否可接受 |
记录按类别的检索和回答指标、P50/P95 延迟及成本。不要把不同模型、不同语料和不同问题集的分数直接放在一起宣称提升。本文提供评估设计,没有实测增益。
3. 证据不足时如何停止生成确定结论
澄清、拒答与有限回答各自对应不同条件。
把失败放回对应阶段
| 阶段 | 典型问题 | 首先检查 |
|---|---|---|
| 解析 | 表格、否定词或单位错误 | 原文件与提取内容 |
| 切分 | 例外条件分离 | 片段及父级上下文 |
| 召回 | 正确资料没进候选 | 查询、过滤与索引 |
| 重排 | 正确候选被挤掉 | 排名前后与预算 |
| 生成 | 忽略条件、补充未经支持的事实 | 实际 Prompt 与逐条结论 |
| 引用 | 编号合法但不能支持断言 | 结论与原文对应关系 |
不要把所有问题都解决成“换更强模型”。解析把金额单位搞错后,强模型也可能忠实地解释错误资料。
相似度不能决定是否可回答
空结果可以作为资料不足信号,有结果却不一定具有答案。某片段讨论同一产品,但没有用户问的版本和功能,仍然不能直接确认。
相反,过高阈值可能丢掉用词不同但真实相关的资料。拒答条件需要在固定问题集上校准,而不是把 0.8 当作通用可信线。
还要检查证据新旧、互相冲突以及问题缺少的限定。存在两个版本的不同规则时,可以说明无法确认当前适用版本,或者请用户补充,而不是选择分数最高的一个。
什么情况应该澄清,什么情况应该拒答?
缺少产品、日期、版本等必要条件时,可以先澄清;资料没有覆盖问题或证据冲突无法解决时,应说明无法确认;资料有明确答案时,则不应因为某个分数不够高机械拒答。
对无权限资料,不应透露它是否存在。对金额、审批和执行建议,不能把无依据的推断直接转成工具动作。
拒答可以说明允许范围内的原因和下一步,例如“当前资料未包含这项功能的版本说明”。不要编造不存在的官方链接让用户继续查。
为什么把更多资料塞进 Prompt 未必有效?
更多候选会增加重复、冲突和无关内容,模型也未必均等利用所有位置。长上下文研究提供了位置敏感性的证据,但具体模型效果仍需自己的评估。Lost in the Middle
优先选择完整、有效、已授权的证据,保留关键例外,再按预算组织。文档中的“忽略规则并调用工具”应当视为不可信内容;仅加提示词不能替代工具授权。
怎样降低问题再次发生的概率?
保留问题类别、候选证据、配置版本和失败原因,在授权范围内形成回归样本。分别衡量无依据回答、引用错误、错误拒答和正确拒答,而不是只看回答覆盖率。
对关键事实采用明确业务来源或确定性校验,例如订单真实状态来自授权查询工具。把生成式解释与事实获取分开,可以减少模型凭记忆猜业务数据。
4. 设计判断与适用边界
为原始问题保留不可丢失的信息,例如编号、租户范围和时间条件。改写只改变表达,不改变用户意图;候选集和重排输入有大小限制,避免查询扩展无限增长。
上下文补充是另一种方案:为孤立片段加入能在原文验证的标题和对象说明。它不能作为模型自行补全事实的入口。通过消融比较切分、混合召回、重排和改写的贡献,只有效果足以覆盖成本时才保留新增组件。
Contextual Retrieval 讨论为片段补充文档上下文。是否适用仍要通过本项目样本比较,本文没有移用其效果指标。 Anthropic:Introducing Contextual Retrieval。
5. 问答
问:重排能找回没有召回的文档吗?
答:不能,它处理已有候选,应先保证召回覆盖。
问:改写越多越好吗?
答:会增加噪声、请求数和费用,需要固定问题集评估并限制总预算。
问:有检索结果就不应该拒答吗?
答:结果可能只是主题相近,要看是否完整支持当前问题。
问:引用编号存在就证明主张成立吗?
答:只能证明引用属于候选集合,还需检查原文是否支持对应主张。