11 Apr, 2026

1 commit

  • 这次代码侧的核心变化是:
    - 删除了 `indexer/product_enrich.py`、`indexer/product_enrich_prompts.py` 及相关单测。
    - 在 [api/routes/indexer.py](/data/saas-search/api/routes/indexer.py:55) 移除了 `/indexer/enrich-content` 路由;现在这个路径在本仓库 indexer 服务里会是 `404`,对应契约测试也已改成校验移除状态:[tests/ci/test_service_api_contracts.py](/data/saas-search/tests/ci/test_service_api_contracts.py:345)。
    - 在 [api/routes/indexer.py](/data/saas-search/api/routes/indexer.py:183)、[indexer/document_transformer.py](/data/saas-search/indexer/document_transformer.py:109)、[indexer/incremental_service.py](/data/saas-search/indexer/incremental_service.py:587)、[indexer/spu_transformer.py](/data/saas-search/indexer/spu_transformer.py:223) 去掉了构建 doc 时自动补 `qanchors` / `enriched_*` 的本地 LLM 富化逻辑。现在 `build-docs` / `reindex` / `index` 只负责基础文档构建。
    - 在 [config/schema.py](/data/saas-search/config/schema.py:316)、[config/loader.py](/data/saas-search/config/loader.py:824)、[config/env_config.py](/data/saas-search/config/env_config.py:37)、[config/config.yaml](/data/saas-search/config/config.yaml:32) 清掉了旧实现专用的 `product_enrich` 和 anchor cache 配置面。
    
    重要文档也一起同步了,重点是把“能力已迁出、本仓库不再内置生成”写明确:
    - [README.md](/data/saas-search/README.md:113)
    - [docs/搜索API对接指南-00-总览与快速开始.md](</data/saas-search/docs/搜索API对接指南-00-总览与快速开始.md:108>)
    - [docs/搜索API对接指南-05-索引接口(Indexer).md](</data/saas-search/docs/搜索API对接指南-05-索引接口(Indexer).md:647>)
    - [docs/搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation).md](</data/saas-search/docs/搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation).md:441>)
    - [docs/工作总结-微服务性能优化与架构.md](</data/saas-search/docs/工作总结-微服务性能优化与架构.md:96>)
    - [docs/缓存与Redis使用说明.md](</data/saas-search/docs/缓存与Redis使用说明.md:186>)
    - [indexer/README.md](/data/saas-search/indexer/README.md:508)
    - [indexer/ANCHORS_AND_SEMANTIC_ATTRIBUTES.md](/data/saas-search/indexer/ANCHORS_AND_SEMANTIC_ATTRIBUTES.md:1)
    
    验证做了两步:
    - `python3 -m compileall ...` 通过
    - `source activate.sh && python -m pytest tests/ci/test_service_api_contracts.py -q` 通过,`31 passed`
    
    剩下我认为仍有“旧信息”但暂时没动的,主要是历史记录类文档,不算当前对接口径:
    - [docs/issues/issue.md](/data/saas-search/docs/issues/issue.md:295)
    - [docs/issues/issue.txt](/data/saas-search/docs/issues/issue.txt:468)
    - [docs/issues/issue-2026-03-29-索引修改-done-0330.md](</data/saas-search/docs/issues/issue-2026-03-29-索引修改-done-0330.md:23>)
    - [docs/issues/issue-2026-04-04-增加多模态标注-TODO.md](</data/saas-search/docs/issues/issue-2026-04-04-增加多模态标注-TODO.md:1>)
    
    另外,工作区里原本就有 `.env` 修改和未跟踪的 `AGENTS.md`,我没有动它们。
    tangwang
     

09 Apr, 2026

3 commits

  • 本次迭代对检索系统的内容复化模块进行了较大规模的重构,将原先硬编码的“仅服饰(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
     
  • 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 切换及兼容模式测试
    tangwang
     
  • - `/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` 组合场景及缓存隔离测试
    tangwang
     

30 Mar, 2026

2 commits


23 Mar, 2026

1 commit


18 Mar, 2026

1 commit

  • 核心改动在 rerank_client.py (line 99):fuse_scores_and_resort 现在按
    rerank * knn * text 的平滑乘法公式计算,优先从 hit["matched_queries"]
    里取 base_query 和 knn_query,并把 _text_score / _knn_score
    一并写回调试字段。为了让 KNN 也有名字,我给 top-level knn 加了 name:
    "knn_query",见 es_query_builder.py (line 273)。搜索执行时会在 rerank
    窗口内打开 include_named_queries_score,并在显式排序时加上
    track_scores,见 searcher.py (line 400) 和 es_client.py (line 224)。
    tangwang
     

17 Mar, 2026

1 commit

  • - 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

1 commit


11 Mar, 2026

2 commits


09 Mar, 2026

2 commits


02 Mar, 2026

1 commit

  • - 新增 /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
     

06 Jan, 2026

1 commit


19 Dec, 2025

1 commit

  • 1. 添加 asyncio 导入
    在文件顶部添加 import asyncio,用于在线程池中执行同步阻塞操作
    2. 修改 /indexer/reindex 路由(全量索引)
    使用 loop.run_in_executor() 将 service.bulk_index() 放到线程池执行
    避免阻塞事件循环,允许其他请求并行处理
    3. 修改 /indexer/index 路由(增量索引)
    使用 loop.run_in_executor() 将 service.index_spus_to_es() 放到线程池执行
    确保全量索引和增量索引可以并行执行
    工作原理
    线程池执行:同步阻塞操作(如数据库查询、ES 写入)在线程池中执行,不阻塞事件循环
    并发支持:
    全量索引占用一个线程
    增量索引可同时使用其他线程
    多个增量请求可并行处理
    资源管理:
    数据库连接池(pool_size=10, max_overflow=20)可支持并发请求
    uvicorn 默认线程池(40 个线程)可处理多个并发请求
    tangwang
     

18 Dec, 2025

2 commits

  • 新增:scripts/recreate_index.py
    功能:初始化 indexer 的 ES/DB 服务,然后调用 BulkIndexingService.bulk_index(…, recreate_index=True) 为指定 tenant_id 做「删除并重建索引 + 全量导入」。
    用法示例:
    cd /home/tw/SearchEngine# 使用默认 batch_size=500python scripts/recreate_index.py 162# 指定 batch_sizepython scripts/recreate_index.py 162 --batch-size 1000
    脚本依赖和 Indexer API 一样的环境变量:DB_HOST/DB_PORT/DB_DATABASE/DB_USERNAME/DB_PASSWORD、ES_HOST/ES_USERNAME/ES_PASSWORD。
    2. 清理与引用更新
    原来的 scripts/recreate_index.sh 已经删除。
    api/routes/indexer.py 里的说明改成引用 scripts/recreate_index.py。
    docs/搜索API对接指南.md 中的提示也从 .sh 改为:
    > python scripts/recreate_index.py <tenant_id> [--batch-size 500]
    tangwang
     
  • 新增 api/indexer_app.py,在独立进程(默认 6004)中初始化 ES + DB + 索引服务,并复用 api/routes/indexer.py 一套路由
    新增 api/service_registry.py,通过注册表向索引路由注入 ES 客户端和索引服务,消除重复代码与循环依赖
    main.py 增加 serve-indexer 子命令;scripts/start.sh / stop.sh / start_backend.sh / start_indexer.sh 支持独立管理索引进程
    文档中所有索引相关示例由 6002/indexer/* 统一调整为 6004/indexer/*
    tangwang
     

09 Dec, 2025

2 commits


08 Dec, 2025

2 commits

  • 新增功能:
    - 新增 POST /indexer/index 增量索引接口,支持按SPU ID列表进行增量索引
    - 新增 indexer/indexer_logger.py 索引日志模块,统一记录全量和增量索引日志到 logs/indexer.log(JSON格式)
    - IncrementalIndexerService 新增 index_spus_to_es 方法,实现增量索引功能
    
    接口重命名:
    - POST /indexer/bulk -> POST /indexer/reindex(全量重建索引)
    - POST /indexer/incremental -> POST /indexer/index(增量索引)
    - POST /indexer/spus -> POST /indexer/documents(查询文档)
    
    日志系统:
    - 全量和增量索引操作统一记录到 logs/indexer.log
    - 记录请求参数、处理过程、ES写入结果、成功/失败统计等关键信息
    - 支持按索引类型、租户ID、SPU ID等维度查询日志
    
    文档更新:
    - 更新接口文档,包含新的接口命名和增量索引接口说明
    - 添加日志查询示例(grep和jq两种方式)
    tangwang
     
  • - 新增批量索引接口: POST /indexer/bulk - 全量索引功能
      - SPU接口改进: POST /indexer/spus - 支持批量获取SPU文档(最多100个)
    
    新增 全量索引服务
    indexer/bulk_indexing_service.py
    
    docs/搜索API对接指南.md
      - 新增索引接口文档: 详细的批量索引和SPU索引接口说明
      - 请求示例: 提供完整的curl命令示例
    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