09 Apr, 2026

3 commits

  • 2. 删掉自动推断 taxonomy profile的逻辑,build_index_content_fields()
    3. 所有 taxonomy profile 都输出 zh/en”,并把按行业切语言的逻辑去掉
       只接受显式传入的 category_taxonomy_profile
    tangwang
     
  • 本次迭代对检索系统的内容复化模块进行了较大规模的重构,将原先硬编码的“仅服饰(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 模板,无需改动其他逻辑。
    tangwang
     
  • 字段生成
    
    - 新增分类法属性富化能力,遵循 enriched_attributes
      相同的字段结构和处理逻辑,仅提示词和解析维度不同
    - 引入 AnalysisSchema
      抽象类,使内容富化(content)与分类法富化(taxonomy)共享批处理、缓存、提示词构建、Markdown
    解析及归一化流程
    - 重构 product_enrich.py 中原有的富化管道,将通用逻辑抽取至
      _process_batch_for_schema、_parse_markdown_to_attributes
    等函数,消除代码重复
    - 在 product_enrich_prompts.py
      中添加分类法提示词模板(TAXONOMY_ANALYSIS_PROMPT)及 Markdown
    表头定义(TAXONOMY_HEADERS)
    - 修复 Markdown
      解析器在空单元格时的行为:原实现会跳过空单元格导致列错位,现改为保留空值,确保稀疏的分类法属性列正确对齐
    - 更新 document_transformer.py 中 build_index_content_fields 函数,将
      enriched_taxonomy_attributes(中/英)写入最终索引文档
    - 调整相关单元测试(test_product_enrich_partial_mode.py
      等)以覆盖新字段路径,测试通过(14 passed)
    
    技术细节:
    - AnalysisSchema 包含
      schema_name、prompt_template、headers、field_name_prefix 等元数据
    -
    缓存键区分内容/分类法:`enrich:{schema_name}:{product_id}`,避免缓存污染
    - 分类法解析使用与 enriched_attributes
      相同的嵌套结构:`{"attribute_key": "value"}`,支持多行表格
    - 批处理大小与重试逻辑保持与原有内容富化一致
    tangwang
     

07 Apr, 2026

1 commit


30 Mar, 2026

2 commits


23 Mar, 2026

1 commit


19 Mar, 2026

1 commit


17 Mar, 2026

3 commits

  • tangwang
     
  • tangwang
     
  • - Rename indexer/product_annotator.py to indexer/product_enrich.py and remove CSV-based CLI entrypoint, keeping only in-memory analyze_products API
    - Introduce dedicated product_enrich logging with separate verbose log file for full LLM requests/responses
    - Change indexer and /indexer/enrich-content API wiring to use indexer.product_enrich instead of indexer.product_annotator, updating tests and docs accordingly
    - Switch translate_prompts to share SUPPORTED_INDEX_LANGUAGES from tenant_config_loader and reuse that mapping for language code → display name
    - Remove hard SUPPORTED_LANGS constraint from LLM content-enrichment flow, driving languages directly from tenant/indexer configuration
    - Redesign LLM prompt generation to support multi-round, multi-language tables: first round in English, subsequent rounds translate the entire table (headers + cells) into target languages using English instructions
    tangwang
     

13 Mar, 2026

4 commits


11 Mar, 2026

1 commit


09 Mar, 2026

3 commits


03 Mar, 2026

1 commit


02 Mar, 2026

3 commits

  • - 新增 indexer/process_products.analyze_products 接口,封装对 DashScope LLM 的调用逻辑,支持 zh/en/de/ru/fr 多语言输出,并结构化返回 anchor_text、tags、usage_scene、target_audience、season、key_attributes、material、features 等字段,既可脚本批处理也可在索引阶段按需调用。
    - 在 SPUDocumentTransformer 中引入 _fill_llm_attributes,按租户 index_languages 与支持语言的交集,对每个 SPU/语言调用 analyze_products,默认开启 LLM 增强:成功时为 doc 填充 qanchors.{lang}(query 风格锚文本)以及 nested semantic_attributes(lang/name/value) 语义维度信息,失败时仅打 warn 日志并优雅降级,不影响主索引链路。
    - 扩展 search_products.json mapping,在商品文档上新增 nested 字段 semantic_attributes(lang/name/value),以通用三元组形式承载 LLM 抽取的场景、人群、材质、风格等可变维度,为后续按语义维度做过滤和分面聚合提供统一的结构化载体。
    - 编写 indexer/ANCHORS_AND_SEMANTIC_ATTRIBUTES.md 设计文档,系统梳理 qanchors 与 semantic_attributes 的字段含义、索引与多语言策略、与 suggestion 构建器的集成方式以及在搜索过滤/分面中的推荐用法,方便后续维护与功能扩展。
    
    Made-with: Cursor
    tangwang
     
  • - 新增 /indexer/build-docs 与 /indexer/build-docs-from-db 接口:前者接收上游传入的 SPU/SKU/Option 原始行数据构建 ES doc(不写 ES),后者在测试场景下基于 tenant_id+spu_ids 内部查库并复用同一套文档构建逻辑
    - 调整增量与全量索引 SQL 与聚合逻辑:移除 shoplazza_product_spu.compare_at_price 读取,统一从 SKU 表聚合最大 compare_at_price,修复 1054 列不存在错误,保证 ES 字段 compare_at_price 来源与索引字段说明v2 保持一致
    - 更新 SPUDocumentTransformer:完善价格区间计算、compare_at_price 聚合以及多语言字段输出,确保输出结构与 mappings/search_products.json、Java 侧 ProductIndexDocument 完全对齐
    - 为 indexer 模块补充 README 与 prompts:系统化说明 Java 调度 + Python 富化的职责划分、翻译缓存方案(Redis translation:{tenant_id}:{target_lang}:{md5(text)})以及 HTTP 接口使用方式
    - 更新顶层 README、搜索API对接指南与测试Pipeline说明:增加关于 indexer 专用服务(serve-indexer, 端口6004)、正式文档构建接口以及手动链路验证(MySQL → build-docs → ES 查询对比)的说明
    - 清理并修正 ES 诊断脚本 docs/常用查询 - ES.md:统一改为 per-tenant 索引 search_products_tenant_{tenant_id},修正过期字段名(keywords 等)和分面聚合字段(去掉 .keyword,使用当前 mapping 中的字段)
    
    Made-with: Cursor
    tangwang
     
  • tangwang
     

21 Feb, 2026

1 commit


27 Jan, 2026

1 commit

  • - config: 新增 SUPPORTED_INDEX_LANGUAGES(38 种语言)、DEFAULT_INDEX_LANGUAGES、
      normalize_index_languages、resolve_index_languages;get_tenant_config 统一注入 index_languages
    - config.yaml: 租户配置改用 index_languages,默认 [en,zh],保留 translate_to_* 兼容解析
    - query/translator: translate_for_indexing 改为接收 index_languages,返回多语言 Dict
    - query/query_parser: 翻译目标从 index_languages 解析,need_wait_translation 按 index_langs 判断
    - search/searcher: enable_translation 改为基于 index_languages 是否非空
    - indexer: document_transformer 按 index_languages 填多语言字段;indexing_utils 仅多语言时初始化翻译器
    - tests: 租户配置与索引测试改为断言 index_languages
    - README: 更新 TODO 说明已支持 index_languages
    tangwang
     

06 Jan, 2026

2 commits

  • tangwang
     
  • mappings/search_products.json:把原来的 title_zh/title_en/brief_zh/... 改成 按语言 key 的对象结构( /products/_doc/1 { "title": {"en":...} } )
    同时在这些字段下 预置了全部 analyzer 语言:
    arabic, armenian, basque, brazilian, bulgarian, catalan, chinese, cjk, czech, danish, dutch, english, finnish, french, galician, german, greek, hindi, hungarian, indonesian, italian, norwegian, persian, portuguese, romanian, russian, spanish, swedish, turkish, thai
    
    实现为 type: object + properties,同时满足“按语言灌入”和“按语言 analyzer”。
    索引灌入(全量/增量/transformer)已同步改完
    indexer/document_transformer.py:输出从 title_zh/title_en/... 改为:
    title: {<primary_lang>: 原文, en?: 翻译, zh?: 翻译}
    brief/description/vendor 同理
    category_path/category_name_text 也改为语言对象(避免查询侧继续依赖旧字段)
    indexer/incremental_service.py:embedding 取值从 title_en/title_zh 改为从 title 对象里优先取 en,否则取 zh,否则取任一可用语言。
    查询侧与配置、API/文档已同步
    search/es_query_builder.py:查询字段统一改成点路径:title.zh / title.en / vendor.zh / vendor.zh.keyword / category_name_text.zh 等。
    config/config.yaml:field boosts / indexes 里的字段名同步为新点路径。
    API & formatter:
    api/result_formatter.py 已支持新结构(并保留对旧 *_zh/_en 的兼容兜底)。
    api/models.py、相关 docs/examples 里的 vendor_zh.keyword 等已更新为 vendor.zh.keyword。
    文档/脚本:docs/、README.md、scripts/ 里所有旧字段名引用已批量替换为新结构。
    tangwang
     

19 Dec, 2025

2 commits


18 Dec, 2025

2 commits

  • config/config_loader.py: 从 QueryConfig 类中删除 enable_translation 字段
    config/config.yaml: 删除 enable_translation: true 配置项
    config/config_loader.py: 从 to_dict() 方法中删除相关输出
    2. 索引阶段(离线)- 使用租户配置
    indexer/indexing_utils.py:
    根据 tenant_config.translate_to_en 和 translate_to_zh 决定是否初始化 translator
    只有任一方向开启时才创建 translator
    indexer/document_transformer.py:
    _fill_text_fields 从 tenant_config 读取 translate_to_en 和 translate_to_zh
    调用 translate_for_indexing 时传递这两个参数
    更新了文档注释
    3. 查询阶段(在线)- 使用租户配置
    query/query_parser.py:
    parse() 方法新增 tenant_id 参数
    根据租户配置决定翻译目标语言(translate_to_zh / translate_to_en)
    如果两个都是 false,跳过翻译阶段
    translator 属性不再依赖 enable_translation,总是可以初始化
    search/searcher.py:
    search() 方法中根据租户配置计算 enable_translation(用于日志和 metadata)
    调用 query_parser.parse() 时传递 tenant_id
    4. 翻译器方法更新
    query/translator.py:
    translate_for_indexing() 新增 translate_to_en 和 translate_to_zh 参数(默认 True 保持向后兼容)
    根据这两个参数决定翻译目标
    更新了文档注释
    tangwang
     
  • 索引的两项功能:
    1. 多语言。 店铺配置的语言如果不等于zh,那么要调用翻译 获得中文翻译结果,同时 如果不等于en,要翻译en的结果。
    要缓存到redis。 先查询缓存,没命中缓存再调用翻译,然后存入redis缓存起来。
    这些逻辑应该是 @query/translator.py 内部的,不需要调用的地方关心。但是现在是  DictCache,直接改掉,改为redis的缓存
    
    2. 填充 标题的向量化字段。如果该店铺的标题向量化打开,那么应该请求向量化模型根据英文的title得到embedding。使用 BgeEncoder.
    
    以上两个模块的缓存,过期时间都是 最近多长时间内没有访问过。
    
    feat:
    1. 更新 REDIS_CONFIG 配置
    在 config/env_config.py 中添加了用户提供的配置项(snapshot_db, translation_cache_expire_days, translation_cache_prefix 等)
    2. 修改 query/translator.py
    将 DictCache 改为 Redis 缓存
    实现了 translate_for_indexing 方法,自动处理多语言翻译:
    如果店铺语言不等于 zh,自动翻译成 zh
    如果店铺语言不等于 en,自动翻译成 en
    翻译逻辑封装在 translator.py 内部,调用方无需关心
    3. 修改 embeddings/text_encoder.py
    在 BgeEncoder 中添加了 Redis 缓存
    实现了滑动过期策略(每次访问时重置过期时间)
    缓存逻辑参考了提供的 CacheManager 对象
    4. 修改 indexer/document_transformer.py
    添加了 encoder 和 enable_title_embedding 参数
    实现了 _fill_title_embedding 方法,使用英文标题(title_en)生成 embedding
    更新了 _fill_text_fields 方法,使用新的 translate_for_indexing 方法
    5. 更新 indexer/indexing_utils.py
    更新了 create_document_transformer 函数,支持新的 encoder 和 enable_title_embedding 参数
    如果启用标题向量化且未提供 encoder,会自动初始化 BgeEncoder
    tangwang
     

07 Dec, 2025

1 commit

  • 主要功能:
    1. 增量数据获取服务
       - 新增 IncrementalIndexerService 提供单个SPU数据获取
       - 新增 /indexer/spu/{spu_id} API接口
       - 服务启动时预加载分类映射等公共数据
       - 提取 SPUDocumentTransformer 统一全量和增量转换逻辑
       - 支持根据租户配置进行语言处理和翻译
    
    3. 租户配置系统
       - 租户配置合并到统一配置文件 config/config.yaml
       - 支持每个租户独立配置主语言和翻译选项
       - 租户162配置为翻译关闭(用于测试)
    
    4. 翻译功能集成
       - 翻译提示词作为DeepL API的context参数传递
       - 支持中英文提示词配置
       - 索引场景:同步翻译,使用缓存
       - 查询场景:异步翻译,立即返回
    
    测试:
    - 新增 indexer/test_indexing.py 和 query/test_translation.py
    - 验证租户162翻译关闭功能
    - 验证全量和增量索引功能
    tangwang