在 Elasticsearch 中使用 LTR 参与检索
1. 为什么需要二阶段排序?
- 首阶段:BM25 / Hybrid / 向量检索 —— 高召回、低成本
- 二阶段:LTR 模型(XGBRanker/LambdaMART)—— 多特征、高精度
将 100~200 条首阶段候选再送入 LTR,可把点击率提升 10-30%(按行业经验)。
2. LTR 模型准备回顾
- Eland 配置 Feature Extractor → 导出训练集
- XGBoost 训练
rank:ndcg
/rank:pairwise
MLModel.import_ltr_model()
传入ltr-model
- Inference 端点自动创建
模型 ID 下文统一写作 ltr-model
。
3. 方案 A:将 LTR 作为 rescorer
GET my-index/_search
{"query": { # 首阶段 BM25"multi_match": {"fields": ["title", "content"],"query": "the quick brown fox"}},"rescore": {"learning_to_rank": { # 二阶段 LTR"model_id": "ltr-model","params": { # 传递给模板 {{query_text}}"query_text": "the quick brown fox"}},"window_size": 100 # 必填:首阶段取前 100}
}
- window_size ≥ from + size。
_score
会被 LTR 预测分覆盖,返回结果按新分值排序。params
与你在特征模板中定义的占位符一一对应。
4. 方案 B:将 LTR 作为 retriever(9.1+)
GET my-index/_search
{"retriever": {"rescorer": {"rescore": { # 与方案 A 同"window_size": 100,"learning_to_rank": {"model_id": "ltr-model","params": { "query_text": "the quick brown fox" }}},"retrievers": [ # 这里定义首阶段“子检索器”{"standard": {"query": { # 可换成 semantic / rrf 等"multi_match": {"fields": ["title", "content"],"query": "the quick brown fox"}}}}]}}
}
为什么需要 retriever 版本?
- 与 RRF、稀疏/稠密向量 等新检索器组合时更加自然;
- 能与 hybrid 查询声明统一;
- 未来便于继续嵌套多级 rescoring。
5. 限制与注意事项
项目 | 说明 |
---|---|
window_size 必填 | LTR 分数与 BM25 不可比,需限制 rescoring 范围;建议 200 以内。 |
分页 | 多页检索时保持 固定 window_size,只改变 from ;否则页间结果可能抖动。 |
评分分布 | LTR 预测分通常 0-1,小于 BM25;如果未设置 rescore,可能被首阶段分数压制。 |
6. 实战建议
-
首阶段 K 值选型
- 电商:
k≈200
兼顾长尾 - 内容 / 文档:
k≈100
足够
- 电商:
-
特征调优
- 点击率、转化率等行为特征要做分桶归一化
-
性能
- 推理延迟 ≈ 0.4 ms / 文档 / 树深度 6
- 可横向扩容 Inference node;或 CPU → GPU 推理
-
灰度发布
- Search Template 参数化
model_id
,AB proxy 按用户分流 - 观察 nDCG / 点击率,确认提升再全量切换
- Search Template 参数化
总结
- Rescorer 用法:最简单直接,在 8.12 即可使用;
- Retriever 用法:9.1 新增,与 RRF/Hybrid 语法更统一;
- 两者核心参数一致:
model_id
、params
、window_size
。
掌握以上 DSL,即可把离线训练好的 LTR 模型接入任何搜索服务,轻松实现 个性化、可学习的多特征排序。祝你的搜索相关性再上一个量级!