这是《LLM 应用开发 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 召回阶段追求“找得到”,重排阶段追求“排得准”。Rerank 模型将查询和候选文档一起编码,能更准确判断细粒度相关性,是提升 RAG 精度的重要环节。
12.1 召回与重排
Query
-> recall top 100
-> filter / dedupe
-> rerank top 100
-> select top 5-10
-> build context
| 阶段 | 目标 | 方法 |
|---|---|---|
| Recall | 高覆盖率 | ANN、BM25、规则 |
| Filter | 安全和硬条件 | 权限、租户、时间 |
| Rerank | 精确相关性 | cross-encoder、模型评分 |
| Select | 控制上下文 | 分数阈值、多样性、token 预算 |
12.2 为什么 Rerank 有效
Embedding 通常分别编码 query 和文档,再用向量距离比较;Rerank 会同时阅读 query 与候选文档,能捕捉词序、条件和排除关系。
示例:
查询:2026 年之后有效的退款政策
候选 A:2025 年退款政策,已失效
候选 B:2026 年生效的退款政策
候选 C:2026 年运费政策
向量可能认为 A 与 B 都相似,Rerank 更容易识别“之后有效”和“退款”的联合条件。
12.3 调用示例
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
def rerank(query: str, documents: list[str]) -> list[int]:
response = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[{
"role": "user",
"content": (
"根据查询给文档排序,只输出 JSON 数组,"
"元素为文档下标,按相关性从高到低排列。\n"
f"查询:{query}\n文档:{documents}"
),
}],
temperature=0,
)
return [int(i) for i in json.loads(response.choices[0].message.content)]
专用 rerank 服务或本地 cross-encoder 通常更适合高并发场景。
12.4 Cross-Encoder
input = [query, document]
model = cross-encoder
output = relevance score
与向量检索对比:
| 维度 | Embedding 召回 | Cross-Encoder 重排 |
|---|---|---|
| 编码方式 | query/doc 分开 | query/doc 一起 |
| 精度 | 中等 | 较高 |
| 延迟 | 低 | 高 |
| 成本 | 可离线建索引 | 每对实时计算 |
| 适合 | 大候选集 | 小候选集 |
因此典型流程是“向量/关键词先缩圈,rerank 精排”。
12.5 候选数量
常见参数:
召回 top K:50-200
重排候选:20-100
最终上下文:3-10 个 chunk
选择依据:
- rerank 延迟;
- 模型成本;
- 候选噪声率;
- 查询意图复杂度;
- 上下文 token 预算;
- 是否还需要人工解释引用。
12.6 选择策略
只按分数取 top N 可能内容重复。
def select_chunks(scored, top_n=8, max_per_doc=2, min_score=0.0):
selected = []
doc_count = {}
for item in sorted(scored, key=lambda x: x["score"], reverse=True):
if item["score"] < min_score:
continue
if doc_count.get(item["doc_id"], 0) >= max_per_doc:
continue
selected.append(item)
doc_count[item["doc_id"]] = doc_count.get(item["doc_id"], 0) + 1
if len(selected) >= top_n:
break
return selected
其他策略:
- 保留父子块;
- 相邻块合并;
- 不同子查询配额;
- 来源多样性;
- 时间最新优先;
- 总 token 预算。
12.7 与业务规则结合
retrieval score
+ rerank score
+ authority score
+ freshness score
- duplicate penalty
- stale penalty
规则示例:
- 官方文档优先于论坛;
- 当前版本优先;
- 生效政策优先;
- 明确答案优先;
- 同一文档最多两段;
- 已被数据库结果否定的候选降级。
12.8 缓存
Rerank 结果可按以下键缓存:
query_normalized
retrieval_set_version
index_version
rerank_model
tenant_id
注意:
- 权限不同不能共享结果;
- 文档更新要失效缓存;
- 只缓存候选 ID 和分数,不缓存敏感正文;
- 设置 TTL;
- 监控命中率。
12.9 评估
| 指标 | 说明 |
|---|---|
| Recall@K before | 重排前召回 |
| Recall@K after | 重排后保留率 |
| Precision@N | 最终上下文相关率 |
| NDCG@N | 排序质量 |
| Answer Correctness | 最终答案正确率 |
| Added Latency | 重排延迟 |
| Added Cost | 重排成本 |
重排可能提高检索指标但降低答案质量,例如把长上下文排除掉,因此最终要看端到端评测。
12.10 常见问题
| 现象 | 排查 |
|---|---|
| 重排慢 | 候选过多、模型太大 |
| 结果不如召回 | 标注不匹配、模型不适合领域 |
| 分数集中 | 归一化或阈值问题 |
| 重复片段多 | 未按 doc 去重 |
| 上下文过长 | top N 和 token 预算 |
| 新文档总靠后 | 新鲜度未参与 |
| 用户看到错误引用 | 引用映射未校验 |
本章小结
Rerank 用更高的计算成本换取更准确的候选排序,适合放在召回和过滤之后。要根据延迟与精度平衡候选数量,结合业务规则、多样性和 token 预算做最终选择,并用端到端答案质量验证收益。
思考题
- 召回和重排的目标有什么不同?
- Cross-Encoder 为什么比双塔向量更精确但更慢?
- 最终上下文选择只看 top 分数有什么问题?
- Rerank 缓存键应包含哪些版本信息?
- 如何证明引入 Rerank 有业务收益?