Commit fb973d19cdee6ce7db1611c9b7a306e3fab08628

Authored by tangwang
1 parent 00c8ddb9

configs

.gitignore
... ... @@ -76,3 +76,4 @@ logs_*/
76 76 .pytest_cache
77 77  
78 78 models/
  79 +model_cache/
... ...
@ deleted
... ... @@ -1,17 +0,0 @@
1   -
2   -# Please enter the commit message for your changes. Lines starting
3   -# with '#' will be ignored, and an empty message aborts the commit.
4   -#
5   -# On branch master
6   -# Your branch is ahead of 'origin/master' by 3 commits.
7   -# (use "git push" to publish your local commits)
8   -#
9   -# Changes to be committed:
10   -# modified: README.md
11   -# modified: docs/Usage-Guide.md
12   -# modified: scripts/service_ctl.sh
13   -# new file: status.sh
14   -#
15   -# Changes not staged for commit:
16   -# modified: third-party/clip-as-service (untracked content)
17   -#
] deleted
... ... @@ -1,17 +0,0 @@
1   -docs
2   -# Please enter the commit message for your changes. Lines starting
3   -# with '#' will be ignored, and an empty message aborts the commit.
4   -#
5   -# On branch master
6   -# Your branch is ahead of 'origin/master' by 5 commits.
7   -# (use "git push" to publish your local commits)
8   -#
9   -# Changes to be committed:
10   -# modified: config/config.yaml
11   -# modified: docs/TODO.txt
12   -# modified: "docs/\346\220\234\347\264\242API\345\257\271\346\216\245\346\214\207\345\215\227-07-\345\276\256\346\234\215\345\212\241\346\216\245\345\217\243\357\274\210Embedding-Reranker-Translation\357\274\211.md"
13   -# modified: "docs/\347\233\270\345\205\263\346\200\247\346\243\200\347\264\242\344\274\230\345\214\226\350\257\264\346\230\216.md"
14   -#
15   -# Changes not staged for commit:
16   -# modified: third-party/clip-as-service (untracked content)
17   -#
config/config.yaml
... ... @@ -131,7 +131,7 @@ function_score:
131 131 # 重排配置(provider/URL 在 services.rerank)
132 132 rerank:
133 133 enabled: true
134   - rerank_window: 384
  134 + rerank_window: 400
135 135 timeout_sec: 15.0
136 136 weight_es: 0.4
137 137 weight_ai: 0.6
... ... @@ -275,7 +275,7 @@ services:
275 275 max_docs: 1000
276 276 normalize: true
277 277 # 服务内后端(reranker 进程启动时读取)
278   - backend: "qwen3_transformers" # bge | qwen3_vllm | qwen3_transformers | dashscope_rerank
  278 + backend: "qwen3_vllm" # bge | qwen3_vllm | qwen3_transformers | dashscope_rerank
279 279 backends:
280 280 bge:
281 281 model_name: "BAAI/bge-reranker-v2-m3"
... ... @@ -296,15 +296,18 @@ services:
296 296 enforce_eager: false
297 297 infer_batch_size: 100
298 298 sort_by_doc_length: true
299   - length_sort_mode: "char" # char | token
300   - instruction: "rank products by given query"
  299 + # "rank products by given query" 比 “Given a query, score the product for relevance” 更好点
  300 + instruction: "rank products by given query"
  301 + # instruction: "Given a query, score the product for relevance"
301 302 qwen3_transformers:
302 303 model_name: "Qwen/Qwen3-Reranker-0.6B"
303 304 instruction: "rank products by given query"
  305 + # instruction: "Score the product’s relevance to the given query"
304 306 max_length: 8192
305 307 batch_size: 64
306 308 use_fp16: true
307   - attn_implementation: "flash_attention_2"
  309 + # sdpa:默认无需 flash-attn;若已安装 flash_attn 可改为 flash_attention_2
  310 + attn_implementation: "sdpa"
308 311 dashscope_rerank:
309 312 model_name: "qwen3-rerank"
310 313 # 按地域选择 endpoint:
... ...
docs/DEVELOPER_GUIDE.md
... ... @@ -360,7 +360,7 @@ services:
360 360 ### 7.6 新增后端清单(以 Qwen3-Reranker 为例)
361 361  
362 362 1. **实现协议**:在 `reranker/backends/qwen3_vllm.py` 中实现类,提供 `score_with_meta(query, docs, normalize) -> (scores, meta)`,输出与 docs 等长且顺序一致。
363   -2. **配置**:在 `config/config.yaml` 的 `services.rerank.backends` 下增加 `qwen3_vllm` 块(model_name、engine、max_model_len、gpu_memory_utilization、`infer_batch_size`、`sort_by_doc_length`、`length_sort_mode` 等);支持环境变量 `RERANK_BACKEND=qwen3_vllm`。
  363 +2. **配置**:在 `config/config.yaml` 的 `services.rerank.backends` 下增加 `qwen3_vllm` 块(model_name、engine、max_model_len、gpu_memory_utilization、`infer_batch_size`、`sort_by_doc_length`等);支持环境变量 `RERANK_BACKEND=qwen3_vllm`。
364 364 3. **注册**:在 `reranker/backends/__init__.py` 的 `get_rerank_backend(name, config)` 中增加 `qwen3_vllm` 分支。
365 365 4. **服务启动**:`reranker/server.py` 启动时根据配置调用 `get_rerank_backend(backend_name, backend_cfg)` 得到实例。
366 366 5. **调用方**:无需修改;仅部署时启动使用新后端的 reranker 服务即可。
... ...
docs/TODO.txt
... ... @@ -21,6 +21,15 @@
21 21 如果有: 先做sku筛选,然后把最优的拼接到名称中,参与reranker。
22 22  
23 23  
  24 +现在在reranker、分页之后、做填充的时候,已经有做sku的筛选。
  25 +需要优化:
  26 +现在是,先做包含的判断,找到第一个 option_value被query包含的,则直接认为匹配。改为
  27 +1. 第一轮:遍历完,如果有且仅有一个才这样。
  28 +2. 第二轮:如果有多个,跳到3。如果没有,对每个词都走泛化词表进行匹配。
  29 +3. 第三轮:如果有多个,那么对这多个,走embedding相关性取最高的。如果一个也没有,则对所有的走embedding相关性取最高的
  30 +这个sku筛选也需要提取为一个独立的模块
  31 +
  32 +
24 33  
25 34 2026-03-21 10:29:23,698 - elastic_transport.transport - INFO - POST http://localhost:9200/search_products_tenant_163/_search?include_named_queries_score=false [status:200 duration:0.009s]
26 35 2026-03-21 10:29:23,700 - request_context - INFO - 分页详情回填 | ids=20 | filled=20 | took=7ms
... ...
docs/工作总结-微服务性能优化与架构.md
... ... @@ -41,7 +41,7 @@
41 41 - **精度**:`dtype: "float16"`,降低显存与计算量。
42 42 - **Prefix Caching**:`enable_prefix_caching: true`,对重复前缀(如相同 query)做缓存,减少重复计算。
43 43 - **CUDA 图**:`enforce_eager: false`(默认),利用 vLLM 的 CUDA graph 降低 kernel 启动开销。
44   -- **按文档长度分批**:`sort_by_doc_length: true`,请求内先按文档长度排序再按 `infer_batch_size` 分批推理,减少 padding 浪费;`length_sort_mode: "char"`(更快,短文本推荐)或 `"token"`(更精确)
  44 +- **按文档长度分批**:`sort_by_doc_length: true`,请求内先按文档长度排序再按 `infer_batch_size` 分批推理,减少 padding 浪费
45 45 - **参数搜索结论**:在 T4、1000-doc 口径下对 `infer_batch_size` 做了 24/32/48/64 对比;**单请求延迟(c=1)** 上 `infer_batch_size=64` 最优,故当前默认 `infer_batch_size: 64`;`max_model_len: 256` 满足 query+doc 短文本场景;`gpu_memory_utilization: 0.36` 与 T4 16GB 匹配。
46 46  
47 47 **具体配置**(`config/config.yaml` → `services.rerank.backends.qwen3_vllm`):
... ... @@ -56,7 +56,6 @@ enable_prefix_caching: true
56 56 enforce_eager: false
57 57 infer_batch_size: 64
58 58 sort_by_doc_length: true
59   -length_sort_mode: "char"
60 59 instruction: "Given a shopping query, rank product titles by relevance"
61 60 ```
62 61 环境变量覆盖:`RERANK_BACKEND`、`RERANKER_SERVICE_URL`、`RERANK_VLLM_INFER_BATCH_SIZE`、`RERANK_VLLM_SORT_BY_DOC_LENGTH` 等。启停:`./scripts/service_ctl.sh start reranker`,健康:`curl -sS http://127.0.0.1:6007/health`。
... ...
docs/搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation).md
... ... @@ -161,7 +161,7 @@ curl "http://localhost:6008/ready"
161 161  
162 162 说明:默认后端为 `qwen3_vllm`(`Qwen/Qwen3-Reranker-0.6B`),需要可用 GPU 显存。
163 163  
164   -补充:`docs` 的请求大小与模型推理 `batch size` 解耦。即使一次传入 1000 条文档,服务端也会按 `services.rerank.backends.qwen3_vllm.infer_batch_size` 自动拆分;若 `sort_by_doc_length=true`,会先按文档长度排序后分批,减少 padding,再按原输入顺序返回分数。`length_sort_mode` 可选 `char`(更快)或 `token`(更精确)
  164 +补充:`docs` 的请求大小与模型推理 `batch size` 解耦。即使一次传入 1000 条文档,服务端也会按 `services.rerank.backends.qwen3_vllm.infer_batch_size` 自动拆分
165 165  
166 166 #### 7.2.1 `POST /rerank` — 结果重排
167 167  
... ...
docs/相关性检索优化说明.md
... ... @@ -267,3 +267,17 @@ python ./scripts/eval_search_quality.py
267 267 3. 源语种不在索引语言,翻译全部失败(验证多目标 fallback)
268 268 4. 自定义 `original_query_fallback_boost_when_translation_missing` 生效
269 269 5. 非 `zh/en` 语种字段动态拼接(如 `de/fr/es`)
  270 +
  271 +
  272 +
  273 +## reranker方面:
  274 +BAAI/bge-reranker-v2-m3的一个严重badcase:
  275 +q=黑色中长半身裙
  276 +
  277 +Rerank score: 0.0785
  278 +title.zh: 2026款韩版高腰显瘦雪尼尔包臀裙灯芯绒开叉中长款咖啡色半身裙女
  279 +title.en: 2026 Korean-style High-waisted Slimming Corduroy Skirt with Slit, Mid-Length Coffee-colored Skirt for Women
  280 +
  281 +Rerank score: 0.9643
  282 +title.en: Black Half-high Collar Base Shirt Women's Autumn and Winter fleece-lined Contrast Color Pure Desire Design Sense Horn Sleeve Ruffled Inner Top
  283 +title.zh: 黑色高领半高领女士秋冬内搭加绒拼色纯欲设计荷叶边袖内衬上衣
... ...
reranker/DEPLOYMENT_AND_TUNING.md
... ... @@ -93,19 +93,14 @@ curl -sS http://127.0.0.1:6007/health
93 93  
94 94 - 调用方一次可传入 1000 docs(业务需求)
95 95 - 服务端按 `infer_batch_size` 自动拆批推理(模型效率需求)
96   -
97   -### 4.2 先排序再分批,降低 padding 浪费
98   -
99 96 - `sort_by_doc_length: true`:按长度排序后再分批
100   -- `length_sort_mode: "char"`:短文本场景下开销更低,默认推荐
101   -- `length_sort_mode: "token"`:长度估计更精确,但有额外 tokenizer 开销
102 97  
103   -### 4.3 全局去重后回填
  98 +### 4.2 全局去重后回填
104 99  
105 100 - 对 docs 进行全局去重(非“仅相邻去重”)
106 101 - 推理后按原请求顺序回填 scores,保证接口契约稳定
107 102  
108   -### 4.4 启动稳定性修复
  103 +### 4.3 启动稳定性修复
109 104  
110 105 - `service_ctl.sh` 对 reranker 使用独立启动路径
111 106 - 增加“稳定健康检查”(连续健康探测)避免“刚 healthy 即退出”的假阳性
... ... @@ -159,7 +154,7 @@ curl -sS http://127.0.0.1:6007/health
159 154  
160 155 ## 7. 生产建议
161 156  
162   -- 默认保持:`infer_batch_size: 64`、`sort_by_doc_length: true`、`length_sort_mode: "char"`
  157 +- 默认保持:`infer_batch_size: 64`、`sort_by_doc_length: true`
163 158 - 满足以下条件时可考虑提高到 `96`:业务以吞吐优先、可接受更高单请求延迟、已通过同机同数据压测验证收益
164 159 - 每次改动后都必须复跑 `benchmark_reranker_1000docs.sh` 并归档结果
165 160  
... ...
reranker/README.md
... ... @@ -24,7 +24,7 @@ Reranker 服务提供统一的 `/rerank` API,支持可插拔后端(BGE、Qwe
24 24 - `reranker/config.py`:服务端口、MAX_DOCS、NORMALIZE 等(后端参数在 config.yaml)
25 25  
26 26 ## 依赖
27   -- 通用:`torch`、`modelscope`、`fastapi`、`uvicorn`(见项目 `requirements.txt` / `requirements_ml.txt`)
  27 +- 通用:`torch`、`transformers`、`fastapi`、`uvicorn`(隔离环境见 `requirements_reranker_service.txt`;全量 ML 环境另见 `requirements_ml.txt`)
28 28 - **Qwen3-vLLM 后端**:`vllm>=0.8.5`、`transformers>=4.51.0`(仅当使用 `backend: qwen3_vllm` 时需 vLLM)
29 29 - **Qwen3-Transformers 后端**:`transformers>=4.51.0`、`torch`(无需 vLLM,适合 CPU 或小显存)
30 30 ```bash
... ... @@ -53,7 +53,6 @@ services:
53 53 max_model_len: 256
54 54 infer_batch_size: 64
55 55 sort_by_doc_length: true
56   - length_sort_mode: "char" # char | token
57 56 enable_prefix_caching: true
58 57 enforce_eager: false
59 58 instruction: "Given a shopping query, rank product titles by relevance"
... ... @@ -157,7 +156,7 @@ uvicorn reranker.server:app --host 0.0.0.0 --port 6007 --log-level info
157 156 ## Notes
158 157 - 无请求级缓存;输入按字符串去重后推理,再按原始顺序回填分数。
159 158 - 空或 null 的 doc 跳过并计为 0。
160   -- **Qwen3-vLLM 分批策略**:`docs` 请求体可为 1000+,服务端会按 `infer_batch_size` 拆分;当 `sort_by_doc_length=true` 时,会先按文档长度排序后分批,减少 padding 开销,最终再按输入顺序回填分数。`length_sort_mode` 支持 `char`(默认,更快)与 `token`(更精确)。
  159 +- **Qwen3-vLLM 分批策略**:`docs` 请求体可为 1000+,服务端会按 `infer_batch_size` 拆分;当 `sort_by_doc_length=true` 时,会先按文档长度排序后分批,减少 padding 开销,最终再按输入顺序回填分数。
161 160 - 运行时可用环境变量临时覆盖批量参数:`RERANK_VLLM_INFER_BATCH_SIZE`、`RERANK_VLLM_SORT_BY_DOC_LENGTH`。
162 161 - **Qwen3-vLLM**:参考 [Qwen3-Reranker-0.6B](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B),需 GPU 与较多显存;与 BGE 相比适合长文本、高吞吐场景(vLLM 前缀缓存)。
163   -- **Qwen3-Transformers**:官方 Transformers Usage 方式,无需 vLLM;适合 CPU 或小显存,可选 `attn_implementation: "flash_attention_2"` 加速。
  162 +- **Qwen3-Transformers**:官方 Transformers Usage 方式,无需 vLLM;适合 CPU 或小显存。默认 `attn_implementation: "sdpa"`;若已安装 `flash_attn` 可设 `flash_attention_2`(未安装时服务会自动回退到 sdpa)。
... ...
reranker/backends/qwen3_vllm.py
... ... @@ -76,7 +76,7 @@ class Qwen3VLLMRerankerBackend:
76 76 dtype = str(self._config.get("dtype", "float16")).strip().lower()
77 77 self._instruction = str(
78 78 self._config.get("instruction")
79   - or "Given a shopping query, rank product titles by relevance"
  79 + or "Given a query, score the product for relevance"
80 80 )
81 81 infer_batch_size = os.getenv("RERANK_VLLM_INFER_BATCH_SIZE") or self._config.get("infer_batch_size", 64)
82 82 sort_by_doc_length = os.getenv("RERANK_VLLM_SORT_BY_DOC_LENGTH")
... ...
reranker/bge_reranker.py
... ... @@ -170,13 +170,14 @@ class BGEReranker:
170 170 output_scores[orig_idx] = float(unique_scores[unique_idx])
171 171  
172 172 # Log per-doc scores (aligned to original docs order)
173   - try:
174   - lines = []
175   - for i, d in enumerate(docs[:100]):
176   - lines.append(f"{output_scores[i]},{'' if d is None else str(d)}")
177   - logger.info("[BGE_RERANKER] query:%s Scores (score,doc):\n%s", query, "\n".join(lines))
178   - except Exception:
179   - pass
  173 + if 0:
  174 + try:
  175 + lines = []
  176 + for i, d in enumerate(docs[:100]):
  177 + lines.append(f"{output_scores[i]},{'' if d is None else str(d)}")
  178 + logger.info("[BGE_RERANKER] query:%s Scores (score,doc):\n%s", query, "\n".join(lines))
  179 + except Exception:
  180 + pass
180 181  
181 182 elapsed_ms = (time.time() - start_ts) * 1000.0
182 183 dedup_ratio = 0.0
... ...