15 Apr, 2026
1 commit
-
背景与问题 - 现有粗排/重排依赖 `knn_query` 和 `image_knn_query` 分数,但这两路分数来自 ANN 召回,并非所有进入 rerank_window (160) 的文档都同时命中文本和图片向量召回,导致部分文档得分为 0,影响融合公式的稳定性。 - 简单扩大 ANN 的 k 无法保证 lexical 召回带来的文档也包含两路向量分;二次查询或拉回向量本地计算均有额外开销且实现复杂。 解决方案 采用 ES rescore 机制,在第一次搜索的 `window_size` 内对每个文档执行精确的向量 script_score,并将分数以 named query 形式附加到 `matched_queries` 中,供后续 coarse/rerank 优先使用。 **设计决策**: - **只补分,不改排序**:rescore 使用 `score_mode: total` 且 `rescore_query_weight: 0.0`,原始 `_score` 保持不变,避免干扰现有排序逻辑,风险最小。 - **精确分数命名**:`exact_text_knn_query` 和 `exact_image_knn_query`,便于客户端识别和回退。 - **可配置**:通过 `exact_knn_rescore_enabled` 开关和 `exact_knn_rescore_window` 控制窗口大小,默认 160。 技术实现细节 1. 配置扩展 (`config/config.yaml`, `config/loader.py`) ```yaml exact_knn_rescore_enabled: true exact_knn_rescore_window: 160 ``` 新增配置项并注入到 `RerankConfig`。 2. Searcher 构建 rescore 查询 (`search/searcher.py`) - 在 `_build_es_search_request` 中,当 `enable_rerank=True` 且配置开启时,构造 rescore 对象: - `window_size` = `exact_knn_rescore_window` - `query` 为一个 `bool` 查询,内嵌两个 `script_score` 子查询,分别计算文本和图片向量的点积相似度: ```painless // exact_text_knn_query (dotProduct(params.query_vector, 'title_embedding') + 1.0) / 2.0 // exact_image_knn_query (dotProduct(params.image_query_vector, 'image_embedding.vector') + 1.0) / 2.0 ``` - 每个 `script_score` 都设置 `_name` 为对应的 named query。 - 注意:当前实现的脚本分数**尚未乘以 knn_text_boost / knn_image_boost**,保持与原始 ANN 分数尺度对齐的后续待办。 3. RerankClient 优先读取 exact 分数 (`search/rerank_client.py`) - 在 `_extract_coarse_signals` 中,从文档的 `matched_queries` 里读取 `exact_text_knn_query` 和 `exact_image_knn_query` 分数。 - 若存在且值有效,则用作 `text_knn_score` / `image_knn_score`,并标记 `text_knn_source='exact_text_knn_query'`。 - 若不存在,则回退到原有的 `knn_query` / `image_knn_query` (ANN 分数)。 - 同时保留原始 ANN 分数到 `approx_text_knn_score` / `approx_image_knn_score` 供调试对比。 4. 调试信息增强 - `debug_info.per_result[*].ranking_funnel.coarse_rank.signals` 中输出 exact 分数、回退分数及来源标记,便于线上观察覆盖率和数值分布。 验证结果 - 通过单元测试 `tests/test_rerank_client.py` 和 `tests/test_search_rerank_window.py`,验证 exact 优先级、配置解析及 ES 请求体结构。 - 线上真实查询采样(6 个 query,top160)显示: - **exact 覆盖率达到 100%**(文本和图片均有分),解决了原 ANN 部分缺失的问题。 - 但 exact 分数与原始 ANN 分数存在量级差异(ANN/exact 中位数比值约 4.1 倍),原因是 exact 脚本未乘 boost 因子。 - 当前排名影响:粗排 top10 重叠度最低降至 1/10,最大排名漂移超过 100。 后续计划 1. 对齐 exact 分与 ANN 分的尺度:在 script_score 中乘以 `knn_text_boost` / `knn_image_boost`,并对长查询额外乘 1.4。 2. 重新评估 top10 重叠度和漂移,若收敛则可将 coarse 融合公式整体迁移至 ES rescore 阶段。 3. 当前版本保持“只补分不改排序”的安全策略,已解决核心的分数缺失问题。 涉及文件 - `config/config.yaml` - `config/loader.py` - `search/searcher.py` - `search/rerank_client.py` - `tests/test_rerank_client.py` - `tests/test_search_rerank_window.py`
14 Apr, 2026
1 commit
-
2. +service_enabled_by_config() { reranker|reranker-fine|translator 如果被关闭,则run.sh all 不启动该服务