混合检索:重排序Reranker
本文介绍如何在 Doris 混合检索中使用模型精排(Reranker),包括 Pure Rerank、Fusion + Rerank 两种使用模式,以及候选数量、模型参数、失败降级和最终排序分数的配置方法。适用于已经获得候选文档,希望通过模型进一步提高结果相关性的场景。
概览
模型精排调用外部 Reranker 服务,对候选文档生成相关性分数,并按照相关性重新排序。最终分数通过虚拟列 __RANK 返回。
Reranker 不替代召回,也不会对全表直接执行搜索。它只处理已经进入候选集的行:
- Pure Rerank 模式下,候选集来自上游子查询、JOIN、CTE 或 UNION。
- Fusion + Rerank 模式下,候选集来自 BM25、ANN 等多路召回的融合结果。
- 未配置
reranker时,查询保持原有 Fusion 排序或上游输入顺序。
1召回 / 上游候选
2 ↓ candidates
3Fusion(可选,RRF / WEIGHT)
4 ↓
5Model Reranker
6 ↓ __RANK
7Post-Process(可选)
8 ↓
9SQL ORDER BY / LIMIT
适用模式
| 模式 | 适用场景 | 写法 |
|---|---|---|
| Pure Rerank | 候选集已由子查询、JOIN、CTE、UNION 构造完成,只需模型精排 | ORDER BY hybrid_search(JSON),不带召回表达式 |
| Fusion + Rerank | 先做 BM25 / ANN 等多路融合,再对 TopK 做模型精排 | ORDER BY hybrid_search(JSON, score_1, score_2, ...),JSON 中带 reranker |
前提条件
两种模式都需要集群已配置 Reranker 服务。执行查询前请确认:
- Pure Rerank 的上游输出中包含
text_columns指定的文本列。 - Fusion + Rerank 中,
bm25_score()列已有倒排索引,ann_distance()列已有向量索引,查询向量维度与索引一致。 - JSON 中的
model名称与 Reranker 服务端一致。 text_columns指定的列为可用文本列,不包含空列表或无法转换的类型。- 生产查询已根据候选规模和模型服务能力设置合理的
candidates。
使用示例
Pure Rerank
Pure Rerank 适合业务已经筛好候选、只需要进行语义重排的场景。此时 hybrid_search() 只接收一个 JSON 字符串,不包含 bm25_score() 或 ann_distance()。
1SELECT id, content, __RANK
2FROM (
3 SELECT id, content
4 FROM documents
5 WHERE tenant_id = 100
6 ORDER BY publish_time DESC
7 LIMIT 200
8) u
9ORDER BY hybrid_search(
10 '{
11 "candidates": 100,
12 "reranker": {
13 "model": "jina-reranker-v2-base-multilingual",
14 "query": "苹果公司市值",
15 "text_columns": ["content"]
16 }
17 }'
18)
19LIMIT 10;
规则:
- JSON 必须包含
reranker对象。 candidates控制送入模型的最大行数。上游行数更多时,按上游输入顺序截取。- 多个 Tablet 并行执行时,未显式设置
ORDER BY和LIMIT的上游输入顺序不稳定。需要稳定候选集时,应在子查询中显式排序并截断。
JOIN、CTE、UNION 同样可以作为上游:
1SELECT id, title, content, author_name, __RANK
2FROM (
3 SELECT
4 d.id,
5 d.title,
6 d.content,
7 a.name AS author_name
8 FROM documents d
9 JOIN authors a ON d.author_id = a.id
10 WHERE d.tenant_id = 100
11 ORDER BY d.publish_time DESC
12 LIMIT 200
13) candidate
14ORDER BY hybrid_search(
15 '{
16 "candidates": 100,
17 "reranker": {
18 "model": "jina-reranker-v2-base-multilingual",
19 "query": "苹果公司市值",
20 "text_columns": ["title", "content", "author_name"],
21 "text_join": "\n"
22 }
23 }'
24)
25LIMIT 10;
Fusion + Rerank
Fusion + Rerank 先通过 BM25、ANN 等方式召回候选,再使用 RRF 或 WEIGHT 融合多路结果,最后调用 Reranker 对融合后的候选进行模型精排。
在原有 RRF / WEIGHT 融合配置中增加 reranker 对象,即可在 Fusion TopK 之后追加模型精排。
1SELECT id, content, __RANK
2FROM documents
3ORDER BY hybrid_search(
4 '{
5 "rerank": "RRF",
6 "c": 60,
7 "candidates": 50,
8 "reranker": {
9 "model": "jina-reranker-v2-base-multilingual",
10 "query": "苹果公司市值",
11 "text_columns": ["content"]
12 }
13 }',
14 bm25_score(content, 'any', '苹果公司市值'),
15 ann_distance(vec, [0.1, 0.2, 0.3, 0.4])
16)
17LIMIT 10;
执行过程:
1BM25 / ANN 召回
2 → RRF / WEIGHT 融合,取前 candidates 条
3 → 调用 Reranker
4 → 按模型分数写入 __RANK 并重排
5 → SQL LIMIT
WEIGHT 融合时需要给出与召回路数一致的权重:
1SELECT id, content, __RANK
2FROM documents
3ORDER BY hybrid_search(
4 '{
5 "rerank": "WEIGHT",
6 "weights": [0.4, 0.6],
7 "candidates": 50,
8 "reranker": {
9 "model": "jina-reranker-v2-base-multilingual",
10 "query": "苹果公司市值",
11 "text_columns": ["title", "content"]
12 }
13 }',
14 bm25_score(content, 'any', '苹果公司市值'),
15 ann_distance(vec, [0.1, 0.2, 0.3, 0.4])
16)
17LIMIT 10;
多表 HYBRID ... ON ... 融合同样可以追加 reranker。多表召回、row-key 对齐和 COALESCE 用法见混合检索相关说明。
查看精排分数
在 SELECT 列表中增加 __RANK,可以查看最终排序分数:
1SELECT id, content, __RANK
2FROM documents
3ORDER BY hybrid_search('{...}', bm25_score(content, 'any', '苹果公司市值'))
4LIMIT 10;
| 虚拟列 | 说明 |
|---|---|
__RANK |
最终排序分数。配置 reranker 且未配置 post_process 时,为模型返回的相关性分数;同时配置 post_process 时,为后处理后的最终分数。 |
hybrid_search() 只支持降序。最终 SQL 按 __RANK DESC 排序,再由外层 LIMIT 截断。
执行完成后,应重点核对:
- 返回结果是否符合
query描述的意图。 __RANK是否按照从高到低的顺序排列。- 实际返回条数是否同时受到候选数量、上游行数和外层
LIMIT的限制。 - 模型服务失败时,结果是否符合当前失败降级配置。
JSON 参数
顶层参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
rerank |
string | Fusion 模式必填 | - | 融合方式,取值 RRF / WEIGHT |
c |
int | 否 | 60 |
RRF 参数,只能与 "rerank": "RRF" 搭配 |
weights |
array | WEIGHT 模式必填 | - | 各路权重,长度必须等于召回路数 |
candidates |
int | 否 | 10 |
进入 Reranker 的最大候选行数,必须写在 JSON 顶层 |
reranker |
object | 使用模型精排时必填 | - | Reranker 配置 |
post_process |
object | 否 | - | 后处理配置,见后处理用户指南 |
candidates 范围是 [1, hybrid_search_reranker_max_candidates],当前默认上限 4000。未配置时,Pure Rerank 和带 Reranker 的融合查询默认使用 hybrid_search_reranker_default_candidates(当前为 10)。生产查询建议显式设置 candidates,并保证它大于最终 LIMIT。
不要把 candidates 写进 reranker 对象。
Reranker 参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
model |
string | 是 | - | Reranker 模型名,需与服务端一致 |
query |
string | 是 | - | 送入模型的查询文本 |
text_columns |
string[] | 是 | - | 作为候选文档内容的文本列,不能为空 |
text_join |
string | 否 | \n |
多列拼接分隔符 |
text_columns 必须是 VARCHAR / CHAR / TEXT / STRING。JSON、VARIANT 或表达式结果需要在子查询中 CAST 成文本并起 alias。存在同名列时,应在子查询中用 alias 消歧;多表场景可以使用限定名,例如 d.content。
多列会按 text_columns 顺序拼接后送给模型,例如 title + \n + content。
失败降级与服务配置
配置失败降级策略
通过会话变量控制 Reranker 调用失败时是否降级:
1SET reranker_fallback_on_failure = true; -- 默认:Reranker 失败时降级
2SET reranker_fallback_on_failure = false; -- 失败时报错
降级行为:
| 模式 | fallback=true 且调用失败 |
|---|---|
| Fusion + Rerank | 保留 Fusion 排序结果,__RANK 不更新为模型分数 |
| Pure Rerank | 保留上游输入顺序,__RANK 保持 0.0 |
参数错误、分数为 NaN / Inf、返回条数不匹配等语义错误不会走降级,查询会直接失败。
查看集群服务配置
BE 配置由集群管理员设置,用户侧通常只需确认服务可用:
1reranker_url = # Rerank API,例如 http://host:port/v1/rerank
2reranker_request_timeout_ms = 3000 # 单次 HTTP 请求超时
3reranker_batch_size = 256 # 单批最大文档数,超出后分批请求
执行语义
- Fusion + Rerank 的模型输入是 Fusion 后的 TopK,不是全表扫描结果。
candidates既影响融合候选规模,也影响送入模型的行数。 - Pure Rerank 按上游到达顺序截取
candidates行。上游应先过滤、排序并限制规模,避免把过大结果集直接送给模型。 - 模型按返回分数降序重排候选,并写入
__RANK。 - 外层
LIMIT在精排之后截断,不参与candidates校验。 - 配置
post_process时,Reranker 之后还会继续调整__RANK;blend只在 Fusion + Rerank 下可用。
常见问题
精排结果不稳定
Pure Rerank 会按照上游输入顺序截取 candidates 行。如果上游查询没有显式设置 ORDER BY 和 LIMIT,多个 Tablet 并行执行时输入顺序可能变化。
请在子查询中先按业务字段排序并限制候选规模,再执行模型精排。
返回结果少于 candidates
candidates 是进入 Reranker 的最大候选数量,不保证实际存在相同数量的候选。上游查询结果较少、Fusion 召回数量不足,或外层 LIMIT 更小时,最终返回条数会相应减少。
Reranker 调用失败但查询没有报错
检查 reranker_fallback_on_failure。当该值为 true 时,模型调用失败会按模式降级:
- Fusion + Rerank 保留 Fusion 排序结果。
- Pure Rerank 保留上游输入顺序,并将
__RANK保持为0.0。
如果需要在模型调用失败时直接终止查询,请将该值设置为 false。
text_columns 配置报错
确认指定列存在,并且列类型为 VARCHAR、CHAR、TEXT 或 STRING。JSON、VARIANT 或表达式结果应先在子查询中转换为文本并设置别名。
推荐实践
- 优先在上游通过业务条件、时间范围或轻量召回缩小候选集,再交给 Reranker。
- 显式设置
candidates,并保证其大于最终LIMIT。 - Pure Rerank 需要稳定结果时,在上游子查询中显式设置
ORDER BY和LIMIT。 - 多列文本应按业务语义确定
text_columns顺序,并通过text_join设置合适的分隔符。 - 生产环境建议保留失败降级,并监控 Reranker 服务调用失败和降级情况。
评价此篇文章
