向量检索评测:相似度高不等于业务命中
向量检索评测:相似度高不等于业务命中
一、Embedding 评测不能只看余弦相似度
向量检索是 RAG、推荐、语义搜索和去重系统的基础。很多实验会展示若干查询的相似度结果,但相似度高并不等于业务命中。Embedding 模型可能偏好字面相似、忽略领域术语,也可能把语义接近但业务含义不同的样本排在前面。
因此向量检索评测需要业务标注。对于问答系统,要标注文档是否能回答问题;对于商品搜索,要标注是否满足用户意图;对于代码检索,要标注片段是否真的可复用。没有标注,只看相似度分布,无法判断模型是否适合场景。
二、检索系统:召回、排序和过滤分开评估
flowchart TD A[查询文本] --> B[Embedding 模型] B --> C[向量索引] C --> D[候选召回] D --> E[业务过滤] E --> F[Rerank] F --> G[TopK 结果]召回阶段关注正确结果是否进入候选集,排序阶段关注正确结果是否排在前面,过滤阶段关注权限、状态、时间范围等业务约束是否正确。把这些环节混在一起,只看最终 TopK,很难定位问题。比如正确文档没有召回,换 rerank 没用;正确文档召回了但排得低,才需要优化排序。
还要注意负样本构造。简单随机负样本往往太容易,模型很快取得高分,但线上遇到的是 hard negative:字面相似、主题相近、领域术语相同但答案不同的样本。评测集需要加入 hard negative,才能暴露模型区分能力。
三、指标实现:MRR 更关注首个正确结果位置
下面示例计算 Mean Reciprocal Rank。它适合关注用户是否能在靠前位置看到正确结果的场景。
def mean_reciprocal_rank(rank_lists, gold_sets): scores = [] for ranked_ids, gold in zip(rank_lists, gold_sets): score = 0.0 for idx, doc_id in enumerate(ranked_ids, start=1): if doc_id in gold: score = 1.0 / idx break scores.append(score) return sum(scores) / max(len(scores), 1)指标要组合使用。Recall@K 衡量是否召回,MRR 衡量首个正确结果位置,nDCG 可以处理多级相关性。对于问答类检索,还可以统计“无证据问题”的误召回率,避免系统在知识库没有答案时仍然返回看似相关的内容。
评测时要固定索引构建参数。向量维度、归一化、距离度量、HNSW 参数、量化方式和过滤条件都会影响结果。只报告模型名称而不报告索引配置,实验不可复现。
四、工程取舍:准确率、延迟和成本共同决定方案
更大的 embedding 模型通常效果更好,但向量生成成本、索引存储和检索延迟也会上升。对在线系统而言,TopK 越大、rerank 越强,端到端延迟越高。评测报告应同时展示质量指标和性能指标,而不是只列命中率。
还要按场景分层。FAQ 检索、长文档检索、代码检索和商品检索对 embedding 的要求不同。一个在通用语义相似度上表现好的模型,未必适合领域缩写和实体密集的业务数据。建议构建多个子集,分别评估短查询、长查询、同义改写、术语查询和无答案查询。
线上反馈要回流。用户点击、停留、追问、人工纠错和最终任务成功都可以作为弱监督信号,但需要去噪。离线评测集用于稳定比较,线上反馈用于发现新分布。两者结合,检索系统才会持续改进。
五、总结
向量检索评测要从业务相关性出发,拆分召回、过滤和排序,结合 Recall@K、MRR、nDCG 和无答案误召回率。相似度高只是模型输出,业务命中才是工程目标。指标、索引配置和性能成本都透明,评测才有意义。
