17 Apr, 2026
3 commits
-
1. deepl performance improve 2. nllb-200-distilled-600m model params optimize
-
【方案落地】 - 配置层:在 config/config.yaml 中注册 core_queries(原53条)和 clothing_top771(771条) 核心改动:config/schema.py (line 410) 增加 EvaluationDataset 模型; config/loader.py (line 304) 提供 get_dataset/list_datasets,兼容旧配置; 新增 scripts/evaluation/eval_framework/datasets.py 作为 dataset registry 辅助模块 - 存储与框架:所有 artifact 按 dataset_id 隔离,标注缓存跨数据集共享 核心改动:store.py (line 1) 增加 dataset_id 字段到 build_runs/batch_runs; framework.py (line 1) build/batch_evaluate 接受 dataset_id 并固化 snapshot - CLI 与调参:所有子命令增加 --dataset-id 参数 核心改动:cli.py (line 1)、tune_fusion.py (line 1) 及启动脚本 - Web 与前端:支持动态切换评估集,History 按 dataset 过滤 核心改动:web_app.py (line 1) 新增 /api/datasets,/api/history 支持 dataset_id; static/index.html 和 eval_web.js (line 1) 增加下拉选择器 【验证与测试】 - 新增 tests/test_search_evaluation_datasets.py,pytest 通过 2 passed - 编译检查通过(pyflakes/mypy 核心模块) - eval-web 已按新模型重启并通过健康检查(后续因资源占用不稳定,不影响标注) 【LLM 标注运行状态】 - 目标 dataset:clothing_top771(771条query) - 手动拉起 reranker(因 search.rerank.enabled=false),确认 /health 正常 - 执行 rebuild --dataset-id clothing_top771,当前已进入第1个 query "白色oversized T-shirt" 的批量标注阶段(llm_batch=24/40) - 日志:logs/eval.log(主进度),logs/verbose/eval_verbose.log(详细 LLM I/O) -
enrich: 20 文本向量化:24 图片向量化:8 翻译: 24
16 Apr, 2026
2 commits
15 Apr, 2026
2 commits
-
修改内容 1. **新增配置项** (`config/config.yaml`) - `exact_knn_rescore_enabled`: 是否开启精确向量重打分,默认 true - `exact_knn_rescore_window`: 重打分窗口大小,默认 160(与 rerank_window 解耦,可独立配置) 2. **ES 查询层改造** (`search/searcher.py`) - 在第一次 ES 搜索中,根据配置为 window_size 内的文档注入 rescore 阶段 - rescore_query 中包含两个 named script_score 子句: - `exact_text_knn_query`: 对文本向量执行精确点积 - `exact_image_knn_query`: 对图片向量执行精确点积 - 当前采用 `score_mode=total` 且 `rescore_query_weight=0.0`,**只补分不改排序**,exact 分仅出现在 `matched_queries` 中 3. **统一向量得分 Boost 逻辑** (`search/es_query_builder.py`) - 新增 `_get_knn_plan()` 方法,集中管理文本/图片 KNN 的 boost 计算规则 - 支持长查询(token 数超过阈值)时文本 boost 额外乘 1.4 倍 - 精确 rescore 与 ANN 召回**共用同一套 boost 规则**,确保分数量纲一致 - 原有 ANN 查询构建逻辑同步迁移至该统一入口 4. **融合阶段得分优先级调整** (`search/rerank_client.py`) - `_build_hit_signal_bundle()` 中统一处理向量得分读取 - 优先从 `matched_queries` 读取 `exact_text_knn_query` / `exact_image_knn_query` - 若不存在则回退到原 `knn_query` / `image_knn_query`(ANN 得分) - 覆盖 coarse_rank、fine_rank、rerank 三个阶段,避免重复补丁 5. **测试覆盖** - `tests/test_es_query_builder.py`: 验证 ANN 与 exact 共用 boost 规则 - `tests/test_search_rerank_window.py`: 验证 rescore 窗口及 named query 正确注入 - `tests/test_rerank_client.py`: 验证 exact 优先、回退 ANN 的逻辑 技术细节 - **精确向量计算脚本** (Painless) ```painless // 文本 (dotProduct + 1.0) / 2.0 (dotProduct(params.query_vector, 'title_embedding') + 1.0) / 2.0 // 图片同理,字段为 'image_embedding.vector' ``` 乘以统一的 boost(来自配置 `knn_text_boost` / `knn_image_boost` 及长查询放大因子)。 - **named query 保留机制** - 主查询中已开启 `include_named_queries_score: true` - rescore 阶段命名的脚本得分会合并到每个 hit 的 `matched_queries` 中 - 通过 `_extract_named_score()` 按名称提取,与原始 ANN 得分访问方式完全一致 - **性能影响** (基于 top160、6 条真实查询、warm-up 后 3 轮平均) - `elasticsearch_search_primary` 耗时: 124.71ms → 136.60ms (+11.89ms, +9.53%) - `total_search` 受其他组件抖动影响较大,不作为主要参考 - 该开销在可接受范围内,未出现超时或资源瓶颈 配置示例 ```yaml search: exact_knn_rescore_enabled: true exact_knn_rescore_window: 160 knn_text_boost: 4.0 knn_image_boost: 4.0 long_query_token_threshold: 8 long_query_text_boost_factor: 1.4 ``` 已知问题与后续计划 - 当前版本经过调参实验发现,开启 exact rescore 后部分 query(强类型约束 + 多风格/颜色相似)的主指标相比 baseline(exact=false)下降约 0.031(0.6009 → 0.5697) - 根因:exact 将 KNN 从稀疏辅助信号变为 dense 排序因子,coarse 阶段排序语义变化,单纯调整现有 `knn_bias/exponent` 无法完全恢复 - 后续迭代方向:**coarse 阶段暂不强制使用 exact**,仅 fine/rerank 优先 exact;或 coarse 采用“ANN 优先,exact 只补缺失”策略,再重新评估 相关文件 - `config/config.yaml` - `search/searcher.py` - `search/es_query_builder.py` - `search/rerank_client.py` - `tests/test_es_query_builder.py` - `tests/test_search_rerank_window.py` - `tests/test_rerank_client.py` - `scripts/evaluation/exact_rescore_coarse_tuning_round2.json` (调参实验记录) -
背景与问题 - 现有粗排/重排依赖 `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 不启动该服务
10 Apr, 2026
1 commit
09 Apr, 2026
6 commits
-
- 数据转换放到 scripts/data_import/README.md - 诊断巡检放到 scripts/inspect/README.md - 运维辅助放到 scripts/ops/README.md - 前端辅助服务放到 scripts/frontend/frontend_server.py - 翻译模型下载放到 scripts/translation/download_translation_models.py - 临时图片补 embedding 脚本收敛成 scripts/maintenance/embed_tenant_image_urls.py - Redis 监控脚本并入 redis/,现在是 scripts/redis/monitor_eviction.py 同时我把真实调用链都改到了新位置: - scripts/start_frontend.sh - scripts/start_cnclip_service.sh - scripts/service_ctl.sh - scripts/setup_translator_venv.sh - scripts/README.md 文档里涉及这些脚本的路径也同步修了,主要是 docs/QUICKSTART.md 和 translation/README.md。 -
问题背景: - scripts/ 目录下混有服务启动、数据转换、性能压测、临时脚本及历史备份目录 - 存在大量中间迭代遗留信息,不利于维护和新人理解 - 现行服务编排已稳定为 service_ctl up all 的集合:tei / cnclip / embedding / embedding-image / translator / reranker / backend / indexer / frontend / eval-web,不再保留 reranker-fine 默认位 调整内容: 1. 根 scripts/ 收敛为运行、运维、环境、数据处理脚本,并新增 scripts/README.md 说明文档 2. 性能/压测/调参脚本整体迁至 benchmarks/ 目录,同步更新 benchmarks/README.md 3. 人工试跑脚本迁至 tests/manual/ 目录,同步更新 tests/manual/README.md 4. 删除明确过时内容: - scripts/indexer__old_2025_11/ - scripts/start.sh - scripts/install_server_deps.sh 5. 同步修正以下文档中的路径及过时描述: - 根目录 README.md - 性能报告相关文档 - reranker/translation 模块文档 技术细节: - 性能测试不放常规 tests/ 的原因:这类脚本依赖真实服务、GPU、模型和环境噪声,不适合作为稳定回归门禁;benchmarks/ 更贴合其定位 - tests/manual/ 仅存放需要人工启动依赖、手工观察结果的接口试跑脚本 - 所有迁移后的 Python 脚本已通过 py_compile 语法校验 - 所有迁移后的 Shell 脚本已通过 bash -n 语法校验 校验结果: - py_compile: 通过 - bash -n: 通过
-
2. 删掉自动推断 taxonomy profile的逻辑,build_index_content_fields() 3. 所有 taxonomy profile 都输出 zh/en”,并把按行业切语言的逻辑去掉 只接受显式传入的 category_taxonomy_profile
-
本次迭代对检索系统的内容复化模块进行了较大规模的重构,将原先硬编码的“仅服饰(apparel)”品类拓展至 taxonomy.md 中定义的所有品类,同时优化了代码结构,降低了扩展新品类的成本。核心设计采用注册表模式(profile registry),按品类 profile 分组进行批处理,并明确区分双语(zh+en)与仅英文(en)输出策略。 【修改内容】 1. 品类支持范围扩展 - 新增支持的品类:3c、bags、pet_supplies、electronics、outdoor、home_appliances、home_living、wigs、beauty、accessories、toys、shoes、sports、others - 所有新品类在 taxonomy 输出阶段仅返回 en 字段,避免多语言字段膨胀 - 保留服饰(apparel)品类的双语输出(zh + en),维持原有业务兼容性 2. 核心代码重构 - `indexer/product_enrich.py` - 新增 `TAXONOMY_PROFILES` 注册表,以数据驱动方式定义每个品类的输出语言、prompt 映射、taxonomy 字段集合 - 重写 `_enrich_taxonomy_batch`:按 profile 分组批量调用 LLM,避免为每个品类编写独立分支 - 引入 `_infer_profile_from_category()` 函数,从 SPU 的 category 字段自动推断所属 profile(用于内部索引路径,解决混合目录默认 fallback 到服饰的问题) - `indexer/product_enrich_prompts.py` - 将原有单一服饰 prompt 重构为 `PROMPT_TEMPLATES` 字典,按 profile 存储不同提示词 - 所有非服饰品类共享一套精简提示模板,仅要求输出 en 字段 - `indexer/document_transformer.py` - 在构建 enrichment 请求时传递 category 信息,供下游按 profile 路由 - 调整 `_build_enrich_batch` 逻辑,使批量请求支持混合品类并正确分组 - `indexer/indexer.py`(API 层) - `/indexer/enrich-content` 接口的请求模型增加可选的 `category_profile` 字段,允许调用方显式指定品类;未指定时由服务端自动推断 - 更新参数校验与错误处理,新增对 `others` 等兜底品类的支持 3. 文档同步更新 - `docs/搜索API对接指南-05-索引接口(Indexer).md`:增加品类 profile 参数说明,标注非服饰品类 taxonomy 仅返回 en 字段 - `docs/搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation).md`:更新 enrichment 微服务的调用示例,体现多品类分组批处理 - `taxonomy.md`:补充各品类的字段清单,明确 en 字段为所有非服饰品类的唯一输出 【技术细节】 - **注册表设计**: ```python TAXONOMY_PROFILES = { "apparel": {"lang": ["zh", "en"], "prompt_key": "apparel", "fields": [...]}, "3c": {"lang": ["en"], "prompt_key": "default", "fields": [...]}, \# ... } ``` 新增品类只需在注册表中添加一项,并确保 `PROMPT_TEMPLATES` 中存在对应的 prompt_key,无需修改控制流逻辑。 - **按 profile 分组批处理**: - 原有实现:所有产品混在一起,使用同一套服饰 prompt,导致非服饰产品被错误填充。 - 重构后:`_enrich_taxonomy_batch` 先根据每个产品的 profile 分组,每组独立构造 LLM 请求,响应结果再按原始顺序合并。分组粒度可配置,避免小分组带来的过多请求开销。 - **自动品类推断**: - 对于内部索引(非显式调用 enrichment 接口的场景),通过 `_infer_profile_from_category` 解析 SPU 的 `category_l1/l2/l3` 字段,映射到最匹配的 profile。映射规则基于关键词匹配(如“手机”->“3c”,“狗粮”->“pet_supplies”),未匹配时 fallback 到 `apparel` 以保证系统平稳过渡。 - **输出字段裁剪**: - 由于 Elasticsearch mapping 中 `enriched_taxonomy_attributes.value` 字段仅存储单个值(不分语言),非服饰品类的 LLM 输出直接写入该字段;服饰品类则使用动态模板 `value.zh` 和 `value.en`。代码中通过 `_apply_lang_output` 函数统一处理。 - **代码量与可维护性**: - 虽然因新增大量品类定义导致总行数略有增长(~+180 行),但条件分支数量从 5 处减少到 1 处(仅 profile 查找)。新增品类的平均成本仅为注册表 3 行 + prompt 模板 10 行,无需改动核心 enrichment 循环。 【影响文件】 - `indexer/product_enrich.py` - `indexer/product_enrich_prompts.py` - `indexer/document_transformer.py` - `indexer/indexer.py` - `docs/搜索API对接指南-05-索引接口(Indexer).md` - `docs/搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation).md` - `taxonomy.md` - `tests/test_product_enrich_partial_mode.py`(适配多 profile 测试用例) - `tests/test_llm_enrichment_batch_fill.py` - `tests/test_process_products_batching.py` 【测试验证】 - 执行单元测试与集成测试:`pytest tests/test_product_enrich_partial_mode.py tests/test_llm_enrichment_batch_fill.py tests/test_process_products_batching.py tests/ci/test_service_api_contracts.py`,全部通过(52 passed) - 手动验证混合目录场景:同时提交服饰与 3c 产品,enrichment 响应中服饰返回双语,3c 仅返回 en,且 taxonomy 字段正确填充。 - 编译检查:`py_compile` 所有修改模块无语法错误。 【注意事项】 - 本次重构未改变现有服饰品类的行为,API 向后兼容(未指定 profile 时仍按服饰处理)。 - 若后续需为某品类增加双语支持,只需修改注册表中的 `lang` 列表并补充 prompt 模板,无需改动其他逻辑。 -
category_taxonomy_profile - 原 analysis_kinds 混用了“增强类型”(content/taxonomy)与“品类特定配置”,不利于扩展不同品类的 taxonomy 分析(如 3C、家居等) - 新增 enrichment_scopes 参数:支持 generic(通用增强,产出 qanchors/enriched_tags/enriched_attributes)和 category_taxonomy(品类增强,产出 enriched_taxonomy_attributes) - 新增 category_taxonomy_profile 参数:指定品类增强使用哪套 profile(当前内置 apparel),每套 profile 包含独立的 prompt、输出列定义、解析规则及缓存版本 - 保留 analysis_kinds 作为兼容别名,避免破坏现有调用方 - 重构内部 taxonomy 分析为 profile registry 模式:新增 _get_taxonomy_schema(profile_name) 函数,根据 profile 动态返回对应的 AnalysisSchema - 缓存 key 现在按“分析类型 + profile + schema 指纹 + 输入字段哈希”隔离,确保不同品类、不同 prompt 版本自动失效 - 更新 API 文档及微服务接口文档,明确新参数语义与使用示例 技术细节: - 修改入口:api/routes/indexer.py 中 enrich-content 端点,解析新参数并向下传递 - 核心逻辑:indexer/product_enrich.py 中 enrich_products_batch 增加 profile 参数;_process_batch_for_schema 根据 scope 和 profile 动态获取 schema - 兼容层:若请求同时提供 analysis_kinds,则映射为 enrichment_scopes(content→generic,taxonomy→category_taxonomy),category_taxonomy_profile 默认为 "apparel" - 测试覆盖:新增 enrichment_scopes 组合、profile 切换及兼容模式测试
-
- `/indexer/enrich-content` 路由`enriched_taxonomy_attributes` 与 `enriched_attributes` 一并返回 - 新增请求参数 `analysis_kinds`(可选,默认 `["content", "taxonomy"]`),允许调用方按需选择内容分析类型,为后续扩展和成本控制预留空间 - 重构缓存策略:将 `content` 与 `taxonomy` 两类分析的缓存完全隔离,缓存 key 包含 prompt 模板、表头、输出字段定义(即 schema 指纹),确保提示词或解析规则变更时自动失效 - 缓存 key 仅依赖真正参与 LLM 输入的字段(`title`、`brief`、`description`),`image_url`、`tenant_id`、`spu_id` 不再污染缓存键,提高缓存命中率 - 更新 API 文档(`docs/搜索API对接指南-05-索引接口(Indexer).md`),说明新增参数与返回字段 技术细节: - 路由层调整:在 `api/routes/indexer.py` 的 enrich-content 端点中,将 `product_enrich.enrich_products_batch` 返回的 `enriched_taxonomy_attributes` 字段显式加入 HTTP 响应体 - `analysis_kinds` 参数透传至底层 `enrich_products_batch`,支持按需跳过某一类分析(如仅需 taxonomy 时减少 LLM 调用) - 缓存指纹计算位于 `product_enrich.py` 的 `_get_cache_key` 函数,对每种 `AnalysisSchema` 独立生成;版本号通过 `schema.version` 或 prompt 内容哈希隐式包含 - 测试覆盖:新增 `analysis_kinds` 组合场景及缓存隔离测试
08 Apr, 2026
2 commits
-
Previously, both `b` and `k1` were set to `0.0`. The original intention was to avoid two common issues in e-commerce search relevance: 1. Over-penalizing longer product titles In product search, a shorter title should not automatically rank higher just because BM25 favors shorter fields. For example, for a query like “遥控车”, a product whose title is simply “遥控车” is not necessarily a better candidate than a product with a slightly longer but more descriptive title. In practice, extremely short titles may even indicate lower-quality catalog data. 2. Over-rewarding repeated occurrences of the same term For longer queries such as “遥控喷雾翻滚多功能车玩具车”, the default BM25 behavior may give too much weight to a term that appears multiple times (for example “遥控”), even when other important query terms such as “喷雾” or “翻滚” are missing. This can cause products with repeated partial matches to outrank products that actually cover more of the user intent. Setting both parameters to zero was an intentional way to suppress length normalization and term-frequency amplification. However, after introducing a `combined_fields` query, this configuration becomes too aggressive. Since `combined_fields` scores multiple fields as a unified relevance signal, completely disabling both effects may also remove useful ranking information, especially when we still want documents matching more query terms across fields to be distinguishable from weaker matches. This update therefore relaxes the previous setting and reintroduces a controlled amount of BM25 normalization/scoring behavior. The goal is to keep the original intent — avoiding short-title bias and excessive repeated-term gain — while allowing the combined query to better preserve meaningful relevance differences across candidates. Expected effect: - reduce the bias toward unnaturally short product titles - limit score inflation caused by repeated occurrences of the same term - improve ranking stability for `combined_fields` queries - better reward candidates that cover more of the overall query intent, instead of those that only repeat a subset of terms
07 Apr, 2026
2 commits
-
2. issues文档
04 Apr, 2026
2 commits
-
Exact Match High Relevant Low Relevant Irrelevant to Fully Relevant Mostly Relevant Weakly Relevant Irrelevant
03 Apr, 2026
2 commits
02 Apr, 2026
2 commits
-
目前在54训练数据里面,拆分44条train + 10 test,训练集显著提升但是test上不及基线 作为基础设施保留,以后可以考虑扩大数据集进行使用
01 Apr, 2026
3 commits
31 Mar, 2026
4 commits
30 Mar, 2026
3 commits
-
…nt.py)、[search/searcher.py](/data/saas-search/search/searcher.py)、[frontend/static/js/app.js](/data/saas-search/frontend/static/js/app.js) 以及 [tests/test_rerank_client.py](/data/saas-search/tests/test_rerank_client.py)。 主要修复内容如下: - 精排现依据融合阶段得分进行排序,而非仅依据原始的 `fine_score`。 - 最终重排不再依赖独立的 `fine_scores` 数组(该数组在精排排序后可能产生同步偏差),而是直接读取命中结果附带的 `_fine_score`。 - 精排与最终重排现均通过同一计算路径生成融合调试信息,该路径同时也决定实际排序结果,从而保证记录逻辑与生产逻辑保持一致。 - 调试信息载荷更加清晰:精排和最终重排阶段都会暴露融合输入/因子以及规范的 `fusion_summary`,前端界面现在会渲染该摘要信息。 主要问题:阶段逻辑重复且存在并行的数据通道:一个通道用于计算排序,另一个通道用于组装调试字段,还有第三个通道用于传递辅助数组。这造成了潜在的差异风险。本次重构通过将阶段得分作为唯一事实来源,并让调试/前端直接消费其输出而非事后重构,降低了该风险。 验证结果: - `./.venv/bin/python -m pytest -q tests/test_rerank_client.py tests/test_search_rerank_window.py` - `./.venv/bin/python -m py_compile search/rerank_client.py search/searcher.py` 结果:`22 passed`。 当前的主流程: 1. Query 解析 2. ES 召回 3. 粗排:只用 ES 内部文本/KNN 信号 4. 款式 SKU 选择 + title suffix 5. 精排:轻量 reranker + 文本/KNN 融合 6. 最终 rerank:重 reranker + fine score + 文本/KNN 融合 7. 分页、补全字段、格式化返回 主控代码在 [searcher.py](/data/saas-search/search/searcher.py),打分与 rerank 细节在 [rerank_client.py](/data/saas-search/search/rerank_client.py),配置定义在 [schema.py](/data/saas-search/config/schema.py) 和 [config.yaml](/data/saas-search/config/config.yaml)。 **先看入口怎么决定走哪条路** 在 [searcher.py:348](/data/saas-search/search/searcher.py#L348) 开始,`search()` 先读租户语言、开关、窗口大小。 关键判断在 [searcher.py:364](/data/saas-search/search/searcher.py#L364) 到 [searcher.py:372](/data/saas-search/search/searcher.py#L372): - `rerank_window` 现在是 80,见 [config.yaml:256](/data/saas-search/config/config.yaml#L256) - `coarse_rank.input_window` 是 700,`output_window` 是 240,见 [config.yaml:231](/data/saas-search/config/config.yaml#L231) - `fine_rank.input_window` 是 240,`output_window` 是 80,见 [config.yaml:245](/data/saas-search/config/config.yaml#L245) 所以如果请求满足 `from_ + size <= rerank_window`,就进入完整漏斗: - ES 实际取前 `700` - 粗排后留 `240` - 精排后留 `80` - 最终 rerank 也只处理这 `80` - 最后再做分页切片 如果请求页超出 80,就不走后面的多阶段漏斗,直接按 ES 原逻辑返回。
27 Mar, 2026
5 commits
-
coarse_rank.output_window -> 再做 SKU 选择和 title suffix -> 精排调用轻量 reranker 裁到 fine_rank.output_window -> 最终重排调用现有 reranker,并在最终融合里加入 fine_score。同时把 reranker client/provider 改成了按 service_profile 选不同 service_url,这样 fine/final 可以共用同一套服务代码,只起不同实例。
-
TODO-keywords限定-done.txt