01 Apr, 2026
6 commits
-
`indexer/product_enrich.py`,不是再补一层判断。 根因有两个:缓存 key 按内容复用,但缓存值里还带着旧商品的 `id/title_input`;同时内部分析结果在历史上混用了 `tags` 和 `enriched_tags`。这样一旦命中旧缓存,`build_index_content_fields()` 会因为 `id` 对不上把结果丢掉,最后对外就变成全空。 现在的处理是: - 内部分析结果统一用 `tags` 作为 LLM/缓存层字段。 - 对外只在 `build_index_content_fields()` 封装时映射成 `enriched_tags`,`enriched_attributes` 里也统一产出 `name="enriched_tags"`。 - 读取缓存时会先做归一化:把旧缓存里的 `enriched_tags` 兼容成内部 `tags`,并把命中的缓存结果重绑到当前请求商品的 `id/title_input`。 - 写缓存时也统一写成归一化后的内部结构,并且空内容不再写入缓存。
31 Mar, 2026
13 commits
-
Made-with: Cursor
30 Mar, 2026
11 commits
-
must里面的两个combined_fields查询,boost分别设置为2和0.6,和其他查询条件一起,都放到should里面,设置minimum_should_match==1 2. 如果keywords_query跟combined_fields主查询的query一样,那么不需要再添加了
-
一、tags字段改支持多语言: spu表tags字段,跟title走一样的翻译逻辑,填入原始语言、zh、en。 检查以下字段,都跟title一样走翻译逻辑 title keywords tags brief description vendor category_path category_name_text 二、/indexer/enrich-content接口的修改 1. 请求参数,把language去掉,因为我返回的内容直接对应索引结构,不用你做处理了,因此不需要指定语言,降低耦合。 2. 返回 enriched_attributes enriched_tags qanchors三个字段,按原始内容填入。 3. enriched_tags是本次新增的,注意区别于tags字段。tags字段来源于mysql spu表,enriched_tags是本接口返回的。 三、specifications的value,需要翻译,也是需要填中英文: { "specifications": [ { "sku_id": "sku-red-s", "name": "color", "value_keyword": "красный", "value_text": { "zh": "红色", "en": "red" } } ] } -
…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
10 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
-
重排融合:之前有knn的配置bias和exponential。现在,文本和图片的embedding相似需要融合,融合方式是dis_max,因此需要配置: 1)各自的权重和tie_breaker 2)整个向量方面的权重(bias和exponential)