10 · 重排序与对话式 RAG:从”能答”到”答得准”
本片目标:解决第 09 篇遗留的两个质量问题——① 检索噪音(用重排序精排);② 多轮追问失准(用历史感知检索)。 新增规定性:10(两段式检索:粗排召回 + 精排重排;查询改写:结合历史) 数据字典:CrossEncoder(sentence_transformers)。 进程线程模型:重排是本地 GPU/CPU 推理;历史感知检索是多一次模型调用。 网络模型:重排本地;历史感知检索 = 1 次模型调用(改写查询)+ 1 次主问答调用。
1. 上集回顾
第 09 篇 RAG 能答了,但两个真实场景会翻车: 场景 A:检索噪音。问”转正需要什么条件”,向量检索召回 3 块,可能第 3 块是”自带电脑补助”——语义距离没拉开。模型被迫在噪音里找答案,容易被带偏。 场景 B:多轮追问。2. 重排序:为什么需要两段式
向量检索(粗排)是”快而粗”:一次把千万块向量算相似度,秒级,但用的是双塔模型(query 和 doc 分别编码,最后算点积)——它牺牲精度换速度。 CrossEncoder(精排)是”慢而准”:把 query 和 doc 拼接成一条喂给模型,做深度交叉注意力——精度高,但一次只能处理一对。 生产方案 = 粗排捞 + 精排挑:3. 数据字典:CrossEncoder
实测分数(2026-08,
models/bge-reranker-base):
4. 重排接入 RAG(代码形态)
5. 对话式 RAG:历史感知检索(查询改写)
问题本质:第 06 篇的对话记忆 + 第 09 篇的 RAG 是两条独立的链,没打通。追问时检索器看到的是残缺的问题。 解法(查询改写,无 agent、无 LangGraph):6. 关键方法(本片完整链路)
7. 进程线程模型
8. 网络模型
9. 验证:跑起来
配套代码code/10_rerank.py(分三幕):
- 重排演示:粗排 k=8 → CrossEncoder 打分 → 观察分数分布(相关 0.98 vs 噪音 0.00);
- 重排接入 RAG:对比有/无重排的答案质量;
- 对话式 RAG:两轮追问,观察改写前后检索命中变化。
10. 边界
- 重排增加延迟:CrossEncoder 逐对推理,粗排 k 越大越慢。k=8~20 是常见区间。
- 改写会漂移:改写模型可能改错原意。生产可在改写失败时回退用原始问题。
- 重排模型要下载:
bge-reranker-base约 1.1GB(本机已在models/)。也可用更小的bge-reranker-v2-m3。 - 粗排 k 必须大于最终 k:精排只从粗排结果里挑,粗排漏了精排救不了。
推荐资料(延伸阅读)
- LangChain 官方文档 · 检索 —— 检索器进阶(含重排概念)
- sentence-transformers 文档 —— CrossEncoder / bge-reranker 的底层库
11. 未完待续
RAG 已经完整(对话 + 重排),能回答文档问题了。但有个天花板:模型只能”说”,不能”做”。 用户问”转正答辩还有几天?“——手册里没有答案,得算出来。你不想为每个问题写死函数。让模型在回答时调用你写的工具(算日期、查系统、发请求)——这就是第 11 篇:工具调用。 → 11 · 工具调用