Blame view

docs/相关性检索优化说明.md 11.3 KB
bcada818   tangwang   last
1
  # 相关性检索优化说明(当前实现)
7bc756c5   tangwang   优化 ES 查询构建
2
  
bcada818   tangwang   last
3
  ## 1. 文档目标
7bc756c5   tangwang   优化 ES 查询构建
4
  
0536222c   tangwang   query parser优化
5
  本文描述当前代码中的文本检索策略,重点覆盖:
7bc756c5   tangwang   优化 ES 查询构建
6
  
bcada818   tangwang   last
7
8
  - 多语言检索路由(`detector` / `translator` / `indexed` 的关系)
  - 统一文本召回表达式(无布尔 AST 分支)
0536222c   tangwang   query parser优化
9
  - 解析层与检索表达式层的职责边界
c90f80ed   tangwang   相关性优化
10
  - 重排融合打分与调试字段
bcada818   tangwang   last
11
  - 典型场景下实际生成的 ES 查询结构
7bc756c5   tangwang   优化 ES 查询构建
12
  
bcada818   tangwang   last
13
  > 说明:向量召回(KNN)是另一维度,本篇仅简要提及,不展开。
7bc756c5   tangwang   优化 ES 查询构建
14
  
bcada818   tangwang   last
15
  ## 2. 核心流程
7bc756c5   tangwang   优化 ES 查询构建
16
  
bcada818   tangwang   last
17
  查询链路(文本相关):
7bc756c5   tangwang   优化 ES 查询构建
18
  
bcada818   tangwang   last
19
  1. `QueryParser.parse()`  
0536222c   tangwang   query parser优化
20
21
22
     负责产出解析事实:`query_normalized`、`rewritten_query`、`detected_language`、`translations`、`query_vector`、`query_tokens`、`contains_chinese`、`contains_english`
  2. `Searcher.search()`  
     负责读取租户 `index_languages`,并将其一方面传给 `QueryParser` 作为 `target_languages`,另一方面传给 `ESQueryBuilder` 作为字段展开约束。
bcada818   tangwang   last
23
  2. `ESQueryBuilder._build_advanced_text_query()`  
0536222c   tangwang   query parser优化
24
     基于 `rewritten_query + detected_language + translations + index_languages` 构建 `base_query` 与 `base_query_trans_*`;并按语言动态拼接 `title/brief/description/vendor/category_*` 的 `.{lang}` 字段,叠加 shared 字段(`tags`、`option*_values`)。
bcada818   tangwang   last
25
26
  3. `build_query()`  
     统一走文本策略,不再有布尔 AST 枝路。
7bc756c5   tangwang   优化 ES 查询构建
27
  
bcada818   tangwang   last
28
  ## 3. 能力矩阵(Detector / Translator / Indexed)
7bc756c5   tangwang   优化 ES 查询构建
29
  
bcada818   tangwang   last
30
  三类能力的职责边界:
7bc756c5   tangwang   优化 ES 查询构建
31
  
bcada818   tangwang   last
32
33
34
  - **Detector**:识别 query 源语言(`detected_language`
  - **Indexed**:租户可检索语言集合(`tenant_config.*.index_languages`
  - **Translator**:源语言到目标语言的可翻译能力及实时成功率
7bc756c5   tangwang   优化 ES 查询构建
35
  
bcada818   tangwang   last
36
  ### 3.1 决策规则
7bc756c5   tangwang   优化 ES 查询构建
37
  
bcada818   tangwang   last
38
39
40
41
  1.`detected_language in index_languages`
     源语言字段做主召回;其他语言走翻译补召回(低权重)。
  2.`detected_language not in index_languages`
     翻译到 `index_languages` 是主路径;源语言字段仅作弱召回。
0536222c   tangwang   query parser优化
42
43
  3. 若翻译部分失败或全部失败:  
     当前实现不会再额外生成“原文打到其他语种字段”的兜底子句;系统保留 `base_query` 并继续执行,可观测性由 `translations` / warning / 命名子句分数提供。
7bc756c5   tangwang   优化 ES 查询构建
44
  
e874eb50   tangwang   docs
45
  ### 3.2 翻译与向量:并发提交与共享超时
7bc756c5   tangwang   优化 ES 查询构建
46
  
0536222c   tangwang   query parser优化
47
  `QueryParser.parse()` 内对翻译与向量采用线程池提交 + **一次** `concurrent.futures.wait`
7bc756c5   tangwang   优化 ES 查询构建
48
  
0536222c   tangwang   query parser优化
49
50
  - **翻译**:对调用方传入的 `target_languages` 中、除 `detected_language` 外的每个目标语种各提交一个 `translator.translate` 任务(多目标时并发执行)。
  - **查询向量**:若开启 `enable_text_embedding`,再提交一个 `text_encoder.encode` 任务。
e874eb50   tangwang   docs
51
  - 上述任务进入**同一** future 集合;例如租户索引为 `[zh, en]` 且检测语种**不在**索引内时,常为 **2 路翻译 + 1 路向量,共 3 个任务并发**,共用超时。
7bc756c5   tangwang   优化 ES 查询构建
52
  
0536222c   tangwang   query parser优化
53
  **等待预算(毫秒)**`detected_language` 是否属于调用方传入的 `target_languages` 决定(`query_config`):
e874eb50   tangwang   docs
54
55
56
57
58
  
  - **在索引内**`translation_embedding_wait_budget_ms_source_in_index`(默认较短,如 80ms)— 主召回已能打在源语种字段,翻译/向量稍慢可容忍。
  - **不在索引内**`translation_embedding_wait_budget_ms_source_not_in_index`(默认较长,如 200ms)— 翻译对可检索文本更关键,给足时间。
  
  超时未完成的任务会被丢弃并记 warning,解析继续(可能无部分译文或无数向量)。
7bc756c5   tangwang   优化 ES 查询构建
59
  
bcada818   tangwang   last
60
  ## 4. 统一文本召回表达式
ea118f2b   tangwang   build_query:根据 qu...
61
  
bcada818   tangwang   last
62
  每个语言子句的基础形态:
ea118f2b   tangwang   build_query:根据 qu...
63
  
bcada818   tangwang   last
64
65
66
  ```json
  {
    "multi_match": {
0536222c   tangwang   query parser优化
67
      "_name": "base_query|base_query_trans_xx",
bcada818   tangwang   last
68
69
70
71
72
73
74
75
      "query": "<text>",
      "fields": ["title.xx^3.0", "brief.xx^1.5", "...", "tags", "option1_values^0.5", "..."],
      "minimum_should_match": "75%",
      "tie_breaker": 0.9,
      "boost": "<按策略决定,可省略>"
    }
  }
  ```
ea118f2b   tangwang   build_query:根据 qu...
76
  
bcada818   tangwang   last
77
  最终按 `bool.should` 组合,`minimum_should_match: 1`
ea118f2b   tangwang   build_query:根据 qu...
78
  
e874eb50   tangwang   docs
79
  > **附 — 混写辅助召回**  
0536222c   tangwang   query parser优化
80
  > 当中英(或多脚本)混写时,为略抬召回:`QueryParser` 用 `contains_chinese`(文中有汉字)、`contains_english`(分词中有长度 ≥3 的纯英文 token)打标;`ESQueryBuilder` 在某一语言的 `multi_match` 上,按规则把**另一语种**的同类字段并入同一 `fields`(受 `index_languages` 限制),并入列的 boost 为配置值再乘 **`mixed_script_merged_field_boost_scale`(默认 0.6,`ESQueryBuilder` 构造参数)**。字段在内部以 `(path, boost)` 列表合并后再格式化为 ES 字符串。
e874eb50   tangwang   docs
81
  
bcada818   tangwang   last
82
  ## 5. 关键配置项(文本策略)
7bc756c5   tangwang   优化 ES 查询构建
83
  
e874eb50   tangwang   docs
84
85
86
87
88
  `query_config` 下与解析等待相关的项:
  
  - `translation_embedding_wait_budget_ms_source_in_index`
  - `translation_embedding_wait_budget_ms_source_not_in_index`
  
bcada818   tangwang   last
89
  位于 `config/config.yaml -> query_config.text_query_strategy`
7bc756c5   tangwang   优化 ES 查询构建
90
  
bcada818   tangwang   last
91
92
  - `base_minimum_should_match`
  - `translation_minimum_should_match`
0536222c   tangwang   query parser优化
93
  - `translation_boost`(所有 `base_query_trans_*` 共用)
bcada818   tangwang   last
94
  - `tie_breaker_base_query`
7bc756c5   tangwang   优化 ES 查询构建
95
  
c90f80ed   tangwang   相关性优化
96
97
  说明:
  
0536222c   tangwang   query parser优化
98
  - `phrase_query` / `keywords_query` 已从当前实现中移除,文本相关性只由 `base_query`、`base_query_trans_*` 两类子句组成。
c90f80ed   tangwang   相关性优化
99
  
bcada818   tangwang   last
100
  ## 6. 典型场景与实际 DSL
7bc756c5   tangwang   优化 ES 查询构建
101
  
bcada818   tangwang   last
102
  以下示例来自当前 `ESQueryBuilder` 生成结果(已按当前代码验证)。
7bc756c5   tangwang   优化 ES 查询构建
103
  
bcada818   tangwang   last
104
  ### 场景 A:源语种已在索引语言中,且翻译成功
7bc756c5   tangwang   优化 ES 查询构建
105
  
bcada818   tangwang   last
106
107
  - `detected_language=de`
  - `index_languages=[de,en]`
0536222c   tangwang   query parser优化
108
109
  - `rewritten_query="herren schuhe"`
  - `translations={en:"men shoes"}`
7bc756c5   tangwang   优化 ES 查询构建
110
  
bcada818   tangwang   last
111
  策略结果:
7bc756c5   tangwang   优化 ES 查询构建
112
  
0536222c   tangwang   query parser优化
113
  - `base_query`:德语字段,**不写** `multi_match.boost`
bcada818   tangwang   last
114
  - `base_query_trans_en`:英语字段,`boost=translation_boost`(默认 0.4)
7bc756c5   tangwang   优化 ES 查询构建
115
  
bcada818   tangwang   last
116
  ### 场景 B:源语种不在索引语言中,部分翻译缺失
7bc756c5   tangwang   优化 ES 查询构建
117
  
bcada818   tangwang   last
118
119
120
  - `detected_language=de`
  - `index_languages=[en,zh]`
  - 只翻译出 `en`,`zh` 失败
7bc756c5   tangwang   优化 ES 查询构建
121
  
bcada818   tangwang   last
122
  策略结果:
7bc756c5   tangwang   优化 ES 查询构建
123
  
0536222c   tangwang   query parser优化
124
125
126
  - `base_query`(德语字段):**不写** `multi_match.boost`(默认 1.0)
  - `base_query_trans_en`(英文字段):`boost=translation_boost`(如 0.4)
  - 不会生成额外中文兜底子句
7bc756c5   tangwang   优化 ES 查询构建
127
  
bcada818   tangwang   last
128
  ### 场景 C:源语种不在索引语言中,翻译全部失败
7bc756c5   tangwang   优化 ES 查询构建
129
  
bcada818   tangwang   last
130
131
  - `detected_language=de`
  - `index_languages=[en,zh]`
0536222c   tangwang   query parser优化
132
  - `translations={}`
7bc756c5   tangwang   优化 ES 查询构建
133
  
bcada818   tangwang   last
134
  策略结果:
7bc756c5   tangwang   优化 ES 查询构建
135
  
0536222c   tangwang   query parser优化
136
137
  - `base_query`(德语字段,**无** `boost` 字段)
  - 不会生成 `base_query_trans_*`
7bc756c5   tangwang   优化 ES 查询构建
138
  
0536222c   tangwang   query parser优化
139
  这意味着当前实现优先保证职责清晰与可解释性,而不是继续在 Builder 内部隐式制造“跨语种原文兜底”。
7bc756c5   tangwang   优化 ES 查询构建
140
  
0536222c   tangwang   query parser优化
141
  ## 7. QueryParser 与 Searcher / ESBuilder 的职责分工
7bc756c5   tangwang   优化 ES 查询构建
142
  
0536222c   tangwang   query parser优化
143
144
145
146
147
148
149
  - `QueryParser` 负责“解析事实”:
    - `query_normalized`
    - `rewritten_query`
    - `detected_language`
    - `translations`
    - `query_vector`
    - `query_tokens`
e874eb50   tangwang   docs
150
    - `contains_chinese` / `contains_english`
0536222c   tangwang   query parser优化
151
152
153
154
  - `Searcher` 负责“租户语境”:
    - `index_languages`
    - 将其传给 parser 作为 `target_languages`
    - 将其传给 builder 作为字段展开约束
bcada818   tangwang   last
155
156
157
  - `ESQueryBuilder` 负责“表达式展开”:
    - 动态字段组装
    - 子句权重分配
0536222c   tangwang   query parser优化
158
159
    - `base_query` / `base_query_trans_*` 子句拼接
    - 跳过“与 base_query 文本和语言完全相同”的重复翻译子句
7bc756c5   tangwang   优化 ES 查询构建
160
  
0536222c   tangwang   query parser优化
161
  这种分层让 parser 不再返回 ES 专用的“语言计划字段”,职责边界更清晰。
7bc756c5   tangwang   优化 ES 查询构建
162
  
c90f80ed   tangwang   相关性优化
163
164
165
166
167
168
  ## 8. 融合打分(Rerank + Text + KNN)
  
  当前融合逻辑位于 `search/rerank_client.py`
  
  ### 8.1 文本相关性大分
  
0536222c   tangwang   query parser优化
169
  文本大分由两部分组成:
c90f80ed   tangwang   相关性优化
170
171
172
  
  - `base_query`
  - `base_query_trans_*`
c90f80ed   tangwang   相关性优化
173
174
175
176
177
  
  聚合方式:
  
  1. `source_score = base_query`
  2. `translation_score = max(base_query_trans_*)`
0536222c   tangwang   query parser优化
178
  3. 加权:
c90f80ed   tangwang   相关性优化
179
180
     - `weighted_source = source_score`
     - `weighted_translation = 0.8 * translation_score`
0536222c   tangwang   query parser优化
181
182
183
  4. 合成:
     - `primary = max(weighted_source, weighted_translation)`
     - `support = weighted_source + weighted_translation - primary`
c90f80ed   tangwang   相关性优化
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
     - `text_score = primary + 0.25 * support`
  
  如果以上子分都缺失,则回退到 ES `_score` 作为 `text_score`,避免纯文本召回被误打成 0。
  
  ### 8.2 最终融合公式
  
  ```python
  fused_score = (
      (rerank_score + 0.00001) *
      (text_score + 0.1) ** 0.35 *
      (knn_score + 0.6) ** 0.2
  )
  ```
  
  设计意图:
  
  - `rerank_score` 是主导信号
  - `text_score` 保留乘法增益,但通过较低指数避免词法高分过度放大
  - `knn_score` 保持弱参与,只作为语义召回补充
  
  ### 8.3 调试字段
  
  开启 `debug=true` 后,`debug_info.per_result` 会暴露:
  
  - `es_score`
  - `rerank_score`
  - `text_score`
  - `text_source_score`
  - `text_translation_score`
c90f80ed   tangwang   相关性优化
213
214
215
216
217
218
219
220
  - `text_primary_score`
  - `text_support_score`
  - `knn_score`
  - `fused_score`
  - `matched_queries`
  
  `debug_info.query_analysis` 还会暴露:
  
0536222c   tangwang   query parser优化
221
222
223
  - `translations`
  - `detected_language`
  - `rewritten_query`
c90f80ed   tangwang   相关性优化
224
225
226
227
  
  这些字段用于检索效果评估与 bad case 归因。
  
  ## 9. 兼容与注意事项
7bc756c5   tangwang   优化 ES 查询构建
228
  
bcada818   tangwang   last
229
230
  1. 当前文本主链路已移除布尔 AST 分支。  
  2. 文档中的旧描述(如 `operator: AND` 固定开启)不再适用,当前实现未强制设置该参数。  
0536222c   tangwang   query parser优化
231
  3. `HanLP` 为必需依赖;当前 parser 不再提供轻量 fallback。  
bcada818   tangwang   last
232
233
234
235
  4. 若后续扩展到更多语种,请确保:
     - mapping 中存在对应 `.<lang>` 字段
     - `index_languages` 配置在支持列表内
     - 翻译 provider 对目标语种可用
7bc756c5   tangwang   优化 ES 查询构建
236
  
c90f80ed   tangwang   相关性优化
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  ## 10. 评估与复现
  
  建议使用项目根目录虚拟环境:
  
  ```bash
  cd /data/saas-search
  source ./activate.sh
  python -m pytest -q tests/test_rerank_client.py tests/test_es_query_builder.py tests/test_search_rerank_window.py tests/test_query_parser_mixed_language.py
  ./scripts/service_ctl.sh restart backend
  sleep 3
  ./scripts/service_ctl.sh status backend
  python ./scripts/eval_search_quality.py
  ```
  
  评估脚本会生成:
  
  - `artifacts/search_eval/search_eval_*.json`
  - `artifacts/search_eval/search_eval_*.md`
  
  可直接从 JSON 中提取 query 级和 result 级调试字段进行分析。
  
  ## 11. 建议测试清单
7bc756c5   tangwang   优化 ES 查询构建
259
  
bcada818   tangwang   last
260
  建议在 `tests/` 增加文本策略用例:
7bc756c5   tangwang   优化 ES 查询构建
261
  
bcada818   tangwang   last
262
  1. 源语种在索引语言,翻译命中缓存  
0536222c   tangwang   query parser优化
263
264
265
  2. 源语种不在索引语言,翻译部分失败(验证仅保留 `base_query` + 成功翻译子句)  
  3. 源语种不在索引语言,翻译全部失败(验证无 `base_query_trans_*` 时仍可正常执行)  
  4.`zh/en` 语种字段动态拼接(如 `de/fr/es`
fb973d19   tangwang   configs
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  
  
  
  ## reranker方面:
  BAAI/bge-reranker-v2-m3的一个严重badcase:
  q=黑色中长半身裙
  
  Rerank score: 0.0785
  title.zh: 2026款韩版高腰显瘦雪尼尔包臀裙灯芯绒开叉中长款咖啡色半身裙女
  title.en: 2026 Korean-style High-waisted Slimming Corduroy Skirt with Slit, Mid-Length Coffee-colored Skirt for Women
  
  Rerank score: 0.9643
  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
  title.zh: 黑色高领半高领女士秋冬内搭加绒拼色纯欲设计荷叶边袖内衬上衣
ef5baa86   tangwang   混杂语言处理
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  
  
  
  qwen3-0.6b的严重badcase:
  q=牛仔裤
  
  Rerank score: 0.0002
  title.en: Wrangler Womens Cowboy Cut Slim Fit Jean Bleach
  title.zh: Wrangler 女士牛仔裤 牛仔剪裁 紧身版型 漂白色
  
  Rerank score: 0.0168
  title.en: Fleece Lined Tights Sheer Women - Fake Translucent Warm Pantyhose Leggings Sheer Thick Tights for Winter
  title.zh: 加绒透肤女士连裤袜 - 仿透视保暖长筒袜 冬季厚款透肤连裤袜
  
  Rerank score: 0.1366
  title.en: Dockers Men's Classic Fit Workday Khaki Smart 360 FLEX Pants (Standard and Big & Tall)
  title.zh: Dockers 男士经典版型工作日卡其色智能360度弹力裤(标准码与加大码)
  
  Rerank score: 0.0981
  title.en: Lazy One Pajama Shorts for Men, Men's Pajama Bottoms, Sleepwear
  title.zh: 懒人男士睡裤,男式家居裤,睡眠服饰