20 Mar, 2026
2 commits
-
ResultFormatter.format_search_results() runs. What changed: For each final paginated SPU hit, the searcher now scans skus[].option1_value against the query text set built from the original query, normalized query, rewritten query, and translations. If no option1_value matches textually, it falls back to embedding similarity and picks the SKU with the highest inner product against the query embedding. The matched SKU is promoted to the front of the SPU’s skus list. The SPU-level image_url is replaced with that matched SKU’s image_src. I left api/result_formatter.py unchanged because it already preserves the SKU order and reads image_url from _source; updating the page hits in searcher makes the formatter return the desired result automatically. Verification: ReadLints on the edited files: no errors Passed targeted tests: pytest tests/test_search_rerank_window.py -k "translated_query or no_direct_option_match"
16 Mar, 2026
1 commit
12 Mar, 2026
1 commit
11 Mar, 2026
1 commit
-
- 前端 JS 不再写死后端地址:默认 API_BASE_URL 为空串,所有搜索与 suggest 请求改为同源路径 (/search/*),仅在显式注入 window.API_BASE_URL 时才覆盖,避免 .env 中旧的 http://43.166.252.75:6002 等配置污染浏览器请求。 - 在 scripts/frontend_server.py 上实现轻量级反向代理:拦截 /search/、/admin/、/indexer/ 的 GET/POST/OPTIONS 请求,服务端将请求转发到本机 6002 (BACKEND_PROXY_URL,默认 http://127.0.0.1:6002),并把响应原样返回前端。 - 通过“浏览器 → web服务器:6003(认证) → GPU:6003(本项目前端) → GPU 本机:6002(后端)”这条链路,彻底绕开 web 服务器 6002 上单独的 Basic Auth,解决了外网访问时前端能打开但搜索请求被 web:6002 拦截的问题。 - frontend_server 默认不再注入 window.API_BASE_URL,只有在设置 FRONTEND_INJECT_API_BASE_URL=1 且 API_BASE_URL 有值时才向 HTML 注入脚本,确保默认行为始终是同源调用,由 6003 统一代理后端。 - 更新 frontend/index.html 中的静态 JS 版本号(tenant_facets_config.js 和 app.js),强制浏览器拉取最新脚本,避免旧版前端继续使用硬编码的后端地址。 Made-with: Cursor
10 Mar, 2026
1 commit
06 Mar, 2026
1 commit
02 Mar, 2026
1 commit
-
- 新增 suggestion 模块(mapping/builder/service),支持按租户构建 `search_suggestions_tenant_{tenant_id}` 索引 - 新增 `main.py build-suggestions` CLI 与 `scripts/build_suggestions.sh`,支持基于商品 title/qanchors 与近 365 天搜索日志的全量构建 - 实现 `/search/suggestions` 接口(多语言 + 结果直达),并接入前端自动补全使用新的后端 API - 为 suggestion 增加 `README` / `RUNBOOK` / `TROUBLESHOOTING` 文档,更新搜索 API 对接指南与速查表 - 补充 `tests/test_suggestions.py` 单元测试,覆盖语言解析和 SuggestionService 查询流程 Made-with: Cursor
27 Dec, 2025
1 commit
-
修改内容 1. 在 tenant_facets_config.js 中添加映射配置 添加 TENANT_ID_MAPPING 配置对象,包含映射关系: 170 → 170 171 → 170 162 → 0 添加 getMappedTenantId() 函数,用于获取映射后的 tenant_id
25 Dec, 2025
1 commit
20 Dec, 2025
1 commit
16 Dec, 2025
2 commits
-
2. 搜索词挖掘
09 Dec, 2025
1 commit
08 Dec, 2025
1 commit
04 Dec, 2025
1 commit
03 Dec, 2025
2 commits
-
{ "facets": [ { "field": "category1_name", "size": 15, "type": "terms" }, "specifications.color", "specifications.size" ] } { "facets": [ {"field": "category1_name", "size": 15, "type": "terms"}, {"field": "specifications.color", "size": 10, "type": "terms"}, {"field": "specifications.size", "size": 10, "type": "terms"} ] } 之前是上面的接口形式,主要是考虑 属性的分面, 因为 款式都是有限的 不需要设定 "size": 10, "type": "terms" 这些参数。 但是从接口设计层面,最好按下面这样,这样的话 specifications.color 和 category1_name 的组装格式 完全一样。前端不需要感知 属性分面 和 类别等其他字段分面的差异。
02 Dec, 2025
3 commits
-
后端请求模型变更(api/models.py) SearchRequest.sku_filter_dimension 从 Optional[str] 改为 Optional[List[str]]。 语义:列表表示一个或多个“维度标签”,例如: 单维度:["color"]、["option1"] 多维度:["color", "size"]、["option1", "option2"] 描述更新为:对 维度组合进行分组,每个组合只保留一个 SKU。 结果格式化与去重逻辑(api/result_formatter.py) ResultFormatter.format_search_results(..., sku_filter_dimension: Optional[List[str]] = None),调用处已同步更新。 单维度旧逻辑升级为多维度逻辑: 新方法:_filter_skus_by_dimensions(skus, dimensions, option1_name, option2_name, option3_name, specifications)。 维度解析规则(按顺序处理,并去重): 若维度是 option1 / option2 / option3 → 对应 option1_value / option2_value / option3_value。 否则,将维度字符串转小写后,分别与 option1_name / option2_name / option3_name 对比,相等则映射到对应的 option*_value。 未能映射到任何字段的维度会被忽略。 对每个 SKU: 按解析出的字段列表(例如 ["option1_value", "option2_value"])取值,组成 key,如 ("red", "L");None 用空串 ""。 按 key 分组,每个 key 只保留遇到的第一个 SKU。 若列表为空或所有维度都无法解析,则 不做过滤,返回原始 skus。 Searcher 参数类型同步(search/searcher.py) Searcher.search(...) 中 sku_filter_dimension 参数类型从 Optional[str] 改为 Optional[List[str]]。 传给 ResultFormatter.format_search_results 时,直接传该列表。 前端参数格式调整(frontend/static/js/app.js) 输入框 #skuFilterDimension 依旧是一个文本框,但解析方式改为: 函数 getSkuFilterDimension(): 读取文本,如:"color" 或 "color,size" 或 "option1, color"。 用逗号 , 拆分,trim() 后过滤空串,返回 字符串数组,例如: "color" → ["color"] "color,size" → ["color", "size"] 若最终数组为空,则返回 null。 搜索请求体中仍使用字段名 sku_filter_dimension,但现在值是 string[] 或 null: body: JSON.stringify({ // ... sku_filter_dimension: skuFilterDimension, // 例如 ["color", "size"] debug: state.debug }) 文档更新(docs/搜索API对接指南.md) 请求体示例中的类型由: "sku_filter_dimension": "string" 改为: "sku_filter_dimension": ["string"] 参数表中: 从 string 改为 array[string],说明为“维度列表,按组合分组,每个组合保留一个 SKU”。 功能说明章节“SKU筛选维度 (sku_filter_dimension)”已调整为 列表语义 + 组合去重,并补充了示例: 单维度: { "query": "芭比娃娃", "sku_filter_dimension": ["color"] } 多维度组合: { "query": "芭比娃娃", "sku_filter_dimension": ["color", "size"] } 使用方式总结 单维度去重(保持旧行为的等价写法) 旧:"sku_filter_dimension": "color" 新:"sku_filter_dimension": ["color"] 多维度组合去重(你新提的需求) 例如希望“每个 SPU 下,同一颜色+尺码组合只保留一个 SKU”: { "query": "芭比娃娃", "sku_filter_dimension": ["color", "size"] } -
sku_filter_dimension=color sku_filter_dimension=option1 / option2 /option3 以上两种方式都可以
-
query config/ranking config优化
29 Nov, 2025
1 commit
14 Nov, 2025
2 commits
13 Nov, 2025
2 commits
-
创建统一配置文件 config/config.yaml(从 base 配置迁移,移除 customer_name) 创建脚本体系 启动、停止、重启、moc数据到mysql、从mysql灌入数据到ES 这些脚本 restart.sh run.sh 内部调用 启动前后端 scripts/mock_data.sh mock数据 -> mysql scripts/ingest.sh mysql->ES
11 Nov, 2025
4 commits
10 Nov, 2025
1 commit
08 Nov, 2025
2 commits