这是一个很实际的工程问题。混合检索的核心在于如何平衡“语义”和“关键字”两种检索的结果,而topk和score(通常指融合后的分数或阈值)就是关键的调节旋钮。
下面给出通用的设置思路和参数策略,你可以根据你的数据场景(比如文档、电商、客服问答)来选择。
1. 核心概念回顾
- 语义检索:用向量表示含义。召回意思相关但字词不同的结果(例如搜“笔记本”,召回“笔记本电脑”)。优点是理解力强,缺点是可能偏离精确关键词。
- 关键字检索:用倒排索引匹配字词。召回字词完全匹配的结果(例如搜“苹果手机”,只召回含这几个字的结果)。优点是精确可控,缺点是无法理解同义词。
- 混合检索:结合两者,用融合算法(如 RRF、加权求和)重排结果。
- TopK:最终返回给用户的结果数量(例如 10 条)。
- Score:融合后分配给每条结果的综合相关性分数,可以设定一个阈值来过滤低质量结果。
2. 关键参数如何设置?
参数一:TopK —— 最终返回多少条结果?
- 设置原则:取决于你的应用场景和 UI 展示能力。
- 推荐范围:10 - 50 条。
- 搜索引擎/问答:10 条。用户只看前几个,多了没用。
- 内容推荐/知识库预览:20 条。给用户更多选择。
- RAG 应用(大模型检索增强):5-10 条。大模型上下文窗口宝贵,太多会分散注意力或引入噪声。
- 注意:为了确保融合效果好,候选池大小(即语义和关键词各自先取多少条)通常设为最终 TopK 的5 到 10 倍。例如,最终要 10 条,各自先取 50-100 条来融合。
参数二:Score —— 如何计算和过滤?
Score 主要涉及两个方面:融合计算方式和过滤阈值。
2.1 融合计算方式(关键!)
两种主流方法:
方法 A:RRF(倒数排名融合)—— 强烈推荐作为起点
- 原理:不关心原始分数绝对值,只关心排名。融合公式:
Score = sum( 1 / (k + rank_i) ),其中k是常数(通常取 60)。 - 优点:不受语义和关键词分数量纲不一致的影响,鲁棒性强,业界常用。
- 如何设置:几乎不用调参,直接用
k=60。它能确保同时出现在两者高排名的文档得分最高。
方法 B:加权求和 —— 需要精细调参
- 原理:
Score = α * 语义相似度 + (1-α) * 关键词相关性。 - 优点:可解释性强,可以精确控制偏向。
- 如何设置
α(语义权重):- 偏关键字场景(如产品型号搜索、法律条文):
α = 0.3或更低。 - 偏语义场景(如长尾问题、同义词丰富的问答):
α = 0.7或更高。 - 均衡场景(大部分通用搜索):
α = 0.5。 - 注意:你需要先将语义分数(如余弦相似度 0-1)和关键词分数(如 BM25 分数,可能 0-20)归一化到同一范围(比如都用 0-1),否则分数高的会主导结果。
- 偏关键字场景(如产品型号搜索、法律条文):
2.2 过滤阈值 —— 用还是不用?
- 不推荐硬性过滤(比如 Score > 0.5 才返回)。原因:Score 是相对排名分,绝对值随查询和文档变化。设高了可能没结果,设低了可能过滤不掉坏结果。
- 推荐的做法:
- 直接用 TopK 控制数量,不用 Score 阈值过滤。
- 如果一定要用,只在单路检索时对原始分数设置一个很低的“垃圾过滤”门槛(比如语义相似度 < 0.2 的直接丢弃),在融合后不要设置。
3. 实战推荐配置
假设你用Elasticsearch 8.x+或有类似 RRF 功能的向量数据库,推荐如下配置:
| 参数 | 推荐值 | 理由 |
|---|---|---|
| 融合算法 | RRF (k=60) | 稳定,无需调参,无视分数尺度问题 |
| 单路召回数 | 200 条 | 给 RRF 足够候选池 |
| 最终 TopK | 10 条 | 用户或大模型能有效处理的数量 |
| Score 阈值 | 不使用 | RRF 分数是动态排名分,无绝对意义 |
伪代码示例:
# 假设使用支持 RRF 的数据库results=hybrid_search(query="如何使用混合检索",semantic_fields=["content_vector"],keyword_fields=["title","content"],rrf_k=60,single_recall_size=200,# 每路取 200final_topk=10,# 最终返回 10 条min_score=None# 不过滤)4. 优化思路:如何调整到最佳状态?
没有万能配置,需要根据你的数据来“调参”。建议建立一个小规模测试集(比如 50-100 个查询和理想结果)。
- 起点:用 RRF,
final_topk=10,single_recall_size=100。 - 观察失败案例:
- 如果发现漏掉了必须精确匹配的结果(如“iPhone 15 Pro Max”被搜出“iPhone 14”):增加关键词权重(改用加权求和,
α=0.3)。 - 如果发现漏掉了意思相关但用词不同的结果(如“如何减肥”搜不出“减脂方法”):增加语义权重(改用加权求和,
α=0.7)。
- 如果发现漏掉了必须精确匹配的结果(如“iPhone 15 Pro Max”被搜出“iPhone 14”):增加关键词权重(改用加权求和,
- 调节 TopK:
- 用户只看第一个结果?TopK=1-3。
- 大模型需要参考多个观点?TopK=5-8。
- 用户像浏览搜索引擎一样往下翻?TopK=20-30。
总结一个简单的决策树
- 刚起步,不想折腾:直接用RRF,
final_topk=10,不要设分数阈值。 - 对精确匹配要求极高:用加权求和,
α=0.2~0.3,final_topk=20。 - 对语义泛化要求高:用加权求和,
α=0.7~0.8,final_topk=20。 - 发现 RRF 结果奇怪:调整 RRF 的
k值(10-100)。k越小,排名越高的文档优势越大;k越大,结果越平均。
你的具体是什么场景?比如是文档搜索、商品搜索,还是 RAG 问答?我可以给你更针对性的参数建议。