用 LoHoSearch 做搜索模型对比,最容易踩的坑不是不会跑命令,而是没先定义“表现”到底是什么。同样一份搜索结果,按“前 5 条是否相关”和“整页排序是否稳定”评估,结论可能完全相反。建议先写下一句可验证的目标,例如“在现有文档集上,对比稀疏检索和稠密检索的前 10 条命中效果”,再开始配置 LoHoSearch。
建议把对比范围限定为同一数据集、同一查询集、同一指标口径下的相对排序。通常路径是:为每个搜索模型准备独立配置,逐组跑同一批查询,记录命中结果、排序和耗时,再结合典型失败案例判断。不要只比较平均分,也不要直接采信单一指标的默认排序;先确认 LoHoSearch 当前版本的指标定义再下结论。
先写清楚要对比什么
对比之前先分类。选型型对比,比如“该用 BM25 还是向量检索”,重点看召回和排序是否覆盖典型查询;调参型对比,比如“同一模型不同权重”,重点看参数变化对排序分布的影响;回归型对比,比如“改动索引配置后结果是否变差”,重点看之前已知的失败案例是否被修复,同时有没有引入新问题。
LoHoSearch 能帮你把查询和文档集固定下来,但对比目标只能由你定。目标最好写成一句话,包含文档集名称、查询集数量和评估重点。写不出来时,先不要急着跑对比。
准备可复现的对比环境
准备三样东西:一份固定版本的文档集、一批能代表真实场景的查询,以及尽可能少的相关性标记。文档集需要固定版本,否则模型 A 和模型 B 跑的不是同一份数据,结果没有可比性。查询集建议 20 到 50 条,覆盖常见词、长尾词、同义改写、命名实体这四类,不需要多,但要有区分度。
LoHoSearch 如果提供配置入口,通常可以让多个模型指向同一个索引。下面的片段只是通用骨架,字段名以你当前环境的实际配置为准:
models:
- name: sparse_baseline
type: sparse
index: product_kb_v1
- name: dense_vector
type: dense
index: product_kb_v1
embedding_model: /models/your-embedding
- name: hybrid_weighted
type: hybrid
index: product_kb_v1
rerank_weight: 0.7
执行时确保三个模型使用同一个索引和同一个查询文件,不要在模型之间更换查询集。如果环境只支持命令行参数,把这份配置里的字段对应到启动参数即可。
逐条记录结果,而不是只看眼感
跑完一个模型后,先导出原始结果,至少要包含查询词、命中文档 ID、排序位置、分值这几列。LoHoSearch 如果提供导出功能,先确认导出字段;如果没有,把每次查询的返回体原样保存下来。关键是所有模型用同一列格式,后面才好合并对比。
建议在批量跑之前,挑 5 条查询人工核对一遍,确认记录下来的顺序和页面上看到的一致。不要假设返回体的第一项就是最优结果,有的工具会混入去重、过滤或业务排序。跑完两个模型后,先把排序差异最大的查询挑出来,这往往是最有价值的分析入口,只看平均分时这类线索会被淹没。
判断哪个模型更好,需要分场景
没有脱离场景的好坏。通常来说,如果文档里的关键信息和查询词高度匹配,稀疏模型的可解释性更强;如果查询词和文档用词不同但语义相同,稠密模型的召回更稳;混合模型能不能兼顾两者,取决于权重与文档集分布,需要结合当前环境确认。
判断顺序建议是:先看两类差异——模型 A 比模型 B 多命中、或排序大幅提前的查询集中在什么类型;再看失败查询是分词问题、索引缺失,还是语义偏差。据此决定胜出模型,而不是只按分数排名。一次对比的结论只适用于当前文档集和查询集,换一批文档后排名可能完全改变,这是正常现象。
快速验证清单
开始正式下结论前,按这份清单检查一遍:
- 文档集是否同一版本,没有中途替换。
- 查询集是否完全一致,是否按相同顺序执行。
- 导出结果是否包含查询词、文档 ID、排序位置和分值。
- 是否至少人工抽查了 5 条查询的实际返回顺序。
- 平均分之外,是否看过差异最大的查询具体长什么样。
- 耗时记录是否在同一批环境压力下采集,只作参考不作主要依据。
清单里任何一项跳过了,结论都要降级为“初步观察”,而不是“对比结果”。