bcada818
tangwang
last
|
1
|
# 相关性检索优化说明(当前实现)
|
7bc756c5
tangwang
优化 ES 查询构建
|
2
|
|
bcada818
tangwang
last
|
3
|
## 1. 文档目标
|
7bc756c5
tangwang
优化 ES 查询构建
|
4
|
|
bcada818
tangwang
last
|
5
|
本文描述当前线上代码的文本检索策略,重点覆盖:
|
7bc756c5
tangwang
优化 ES 查询构建
|
6
|
|
bcada818
tangwang
last
|
7
8
9
|
- 多语言检索路由(`detector` / `translator` / `indexed` 的关系)
- 统一文本召回表达式(无布尔 AST 分支)
- 翻译缺失时的兜底策略
|
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()`
|
e874eb50
tangwang
docs
|
20
|
输出 `detected_language`、`query_text_by_lang`、`search_langs`、`index_languages`、`source_in_index_languages`;另输出 `contains_chinese` / `contains_english`(仅服务混写辅助召回,见 §4 末)。
|
bcada818
tangwang
last
|
21
|
2. `ESQueryBuilder._build_advanced_text_query()`
|
e874eb50
tangwang
docs
|
22
|
按 `search_langs` 动态拼接 `title/brief/description/vendor/category_*` 的 `.{lang}` 字段,叠加 shared 字段(`tags`、`option*_values`);若命中混写辅助条件,在同一子句内并入另一语种列(§4 末)。
|
bcada818
tangwang
last
|
23
24
|
3. `build_query()`
统一走文本策略,不再有布尔 AST 枝路。
|
7bc756c5
tangwang
优化 ES 查询构建
|
25
|
|
bcada818
tangwang
last
|
26
|
## 3. 能力矩阵(Detector / Translator / Indexed)
|
7bc756c5
tangwang
优化 ES 查询构建
|
27
|
|
bcada818
tangwang
last
|
28
|
三类能力的职责边界:
|
7bc756c5
tangwang
优化 ES 查询构建
|
29
|
|
bcada818
tangwang
last
|
30
31
32
|
- **Detector**:识别 query 源语言(`detected_language`)
- **Indexed**:租户可检索语言集合(`tenant_config.*.index_languages`)
- **Translator**:源语言到目标语言的可翻译能力及实时成功率
|
7bc756c5
tangwang
优化 ES 查询构建
|
33
|
|
bcada818
tangwang
last
|
34
|
### 3.1 决策规则
|
7bc756c5
tangwang
优化 ES 查询构建
|
35
|
|
bcada818
tangwang
last
|
36
37
38
39
40
41
|
1. 若 `detected_language in index_languages`:
源语言字段做主召回;其他语言走翻译补召回(低权重)。
2. 若 `detected_language not in index_languages`:
翻译到 `index_languages` 是主路径;源语言字段仅作弱召回。
3. 若第 2 步翻译部分失败或全部失败:
对缺失翻译的 `index_languages` 字段,追加“原文低权重兜底”子句,避免完全丢失这些语种索引面的召回机会。
|
7bc756c5
tangwang
优化 ES 查询构建
|
42
|
|
e874eb50
tangwang
docs
|
43
|
### 3.2 翻译与向量:并发提交与共享超时
|
7bc756c5
tangwang
优化 ES 查询构建
|
44
|
|
e874eb50
tangwang
docs
|
45
|
`QueryParser.parse()` 内(Stage 4–6)对**离线调用**采用线程池提交 + **一次** `concurrent.futures.wait`:
|
7bc756c5
tangwang
优化 ES 查询构建
|
46
|
|
e874eb50
tangwang
docs
|
47
48
49
|
- **翻译**:对 `index_languages` 中除 `detected_language` 外的每个目标语种各提交一个 `translator.translate` 任务(多目标时并发执行)。
- **查询向量**(若开启 `enable_text_embedding` 且域为 default):再提交一个 `text_encoder.encode` 任务。
- 上述任务进入**同一** future 集合;例如租户索引为 `[zh, en]` 且检测语种**不在**索引内时,常为 **2 路翻译 + 1 路向量,共 3 个任务并发**,共用超时。
|
7bc756c5
tangwang
优化 ES 查询构建
|
50
|
|
e874eb50
tangwang
docs
|
51
52
53
54
55
56
|
**等待预算(毫秒)**由 `detected_language` 是否属于租户 `index_languages` 决定(`query_config`):
- **在索引内**:`translation_embedding_wait_budget_ms_source_in_index`(默认较短,如 80ms)— 主召回已能打在源语种字段,翻译/向量稍慢可容忍。
- **不在索引内**:`translation_embedding_wait_budget_ms_source_not_in_index`(默认较长,如 200ms)— 翻译对可检索文本更关键,给足时间。
超时未完成的任务会被丢弃并记 warning,解析继续(可能无部分译文或无数向量)。
|
7bc756c5
tangwang
优化 ES 查询构建
|
57
|
|
bcada818
tangwang
last
|
58
|
## 4. 统一文本召回表达式
|
ea118f2b
tangwang
build_query:根据 qu...
|
59
|
|
bcada818
tangwang
last
|
60
|
每个语言子句的基础形态:
|
ea118f2b
tangwang
build_query:根据 qu...
|
61
|
|
bcada818
tangwang
last
|
62
63
64
65
66
67
68
69
70
71
72
73
|
```json
{
"multi_match": {
"_name": "base_query|base_query_trans_xx|fallback_original_query_xx",
"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...
|
74
|
|
bcada818
tangwang
last
|
75
|
最终按 `bool.should` 组合,`minimum_should_match: 1`。
|
ea118f2b
tangwang
build_query:根据 qu...
|
76
|
|
e874eb50
tangwang
docs
|
77
78
79
|
> **附 — 混写辅助召回**
> 当中英(或多脚本)混写时,为略抬召回:`QueryParser` 用 `contains_chinese`(文中有汉字)、`contains_english`(分词中有长度 ≥3 的纯英文 token)打标;`ESQueryBuilder` 在某一语言的 `multi_match` 上,按规则把**另一语种**的同类字段并入同一 `fields`(受 `index_languages` 限制),并入列的 boost 为配置值再乘 **`mixed_script_merged_field_boost_scale`(默认 0.8,`ESQueryBuilder` 构造参数)**。`fallback_original_query_*` 同样适用。字段在内部以 `(path, boost)` 列表合并后再格式化为 ES 字符串。
|
bcada818
tangwang
last
|
80
|
## 5. 关键配置项(文本策略)
|
7bc756c5
tangwang
优化 ES 查询构建
|
81
|
|
e874eb50
tangwang
docs
|
82
83
84
85
86
|
`query_config` 下与解析等待相关的项:
- `translation_embedding_wait_budget_ms_source_in_index`
- `translation_embedding_wait_budget_ms_source_not_in_index`
|
bcada818
tangwang
last
|
87
|
位于 `config/config.yaml -> query_config.text_query_strategy`:
|
7bc756c5
tangwang
优化 ES 查询构建
|
88
|
|
bcada818
tangwang
last
|
89
90
91
92
93
94
|
- `base_minimum_should_match`
- `translation_minimum_should_match`
- `translation_boost`
- `translation_boost_when_source_missing`
- `source_boost_when_missing`
- `original_query_fallback_boost_when_translation_missing`(新增)
|
bcada818
tangwang
last
|
95
|
- `tie_breaker_base_query`
|
7bc756c5
tangwang
优化 ES 查询构建
|
96
|
|
bcada818
tangwang
last
|
97
|
新增项说明:
|
7bc756c5
tangwang
优化 ES 查询构建
|
98
|
|
bcada818
tangwang
last
|
99
100
|
- `original_query_fallback_boost_when_translation_missing`:
当源语种不在索引语言且翻译缺失时,原文打到缺失目标语字段的低权重系数,默认 `0.2`。
|
7bc756c5
tangwang
优化 ES 查询构建
|
101
|
|
c90f80ed
tangwang
相关性优化
|
102
103
104
105
|
说明:
- `phrase_query` / `keywords_query` 已从当前实现中移除,文本相关性只由 `base_query`、`base_query_trans_*`、`fallback_original_query_*` 三类子句组成。
|
bcada818
tangwang
last
|
106
|
## 6. 典型场景与实际 DSL
|
7bc756c5
tangwang
优化 ES 查询构建
|
107
|
|
bcada818
tangwang
last
|
108
|
以下示例来自当前 `ESQueryBuilder` 生成结果(已按当前代码验证)。
|
7bc756c5
tangwang
优化 ES 查询构建
|
109
|
|
bcada818
tangwang
last
|
110
|
### 场景 A:源语种已在索引语言中,且翻译成功
|
7bc756c5
tangwang
优化 ES 查询构建
|
111
|
|
bcada818
tangwang
last
|
112
113
114
|
- `detected_language=de`
- `index_languages=[de,en]`
- `query_text_by_lang={de:"herren schuhe", en:"men shoes"}`
|
7bc756c5
tangwang
优化 ES 查询构建
|
115
|
|
bcada818
tangwang
last
|
116
|
策略结果:
|
7bc756c5
tangwang
优化 ES 查询构建
|
117
|
|
bcada818
tangwang
last
|
118
119
|
- `base_query`:德语字段,正常权重
- `base_query_trans_en`:英语字段,`boost=translation_boost`(默认 0.4)
|
7bc756c5
tangwang
优化 ES 查询构建
|
120
|
|
bcada818
tangwang
last
|
121
|
### 场景 B:源语种不在索引语言中,部分翻译缺失
|
7bc756c5
tangwang
优化 ES 查询构建
|
122
|
|
bcada818
tangwang
last
|
123
124
125
|
- `detected_language=de`
- `index_languages=[en,zh]`
- 只翻译出 `en`,`zh` 失败
|
7bc756c5
tangwang
优化 ES 查询构建
|
126
|
|
bcada818
tangwang
last
|
127
|
策略结果:
|
7bc756c5
tangwang
优化 ES 查询构建
|
128
|
|
bcada818
tangwang
last
|
129
130
131
|
- `base_query`(德语字段):`boost=source_boost_when_missing`(默认 0.6)
- `base_query_trans_en`(英文字段):`boost=translation_boost_when_source_missing`(默认 1.0)
- `fallback_original_query_zh`(中文字段):原文低权重兜底(默认 0.2)
|
7bc756c5
tangwang
优化 ES 查询构建
|
132
|
|
bcada818
tangwang
last
|
133
|
### 场景 C:源语种不在索引语言中,翻译全部失败
|
7bc756c5
tangwang
优化 ES 查询构建
|
134
|
|
bcada818
tangwang
last
|
135
136
137
|
- `detected_language=de`
- `index_languages=[en,zh]`
- `query_text_by_lang` 仅有 `de`
|
7bc756c5
tangwang
优化 ES 查询构建
|
138
|
|
bcada818
tangwang
last
|
139
|
策略结果:
|
7bc756c5
tangwang
优化 ES 查询构建
|
140
|
|
bcada818
tangwang
last
|
141
142
143
|
- `base_query`(德语字段,低权重)
- `fallback_original_query_en`(英文字段原文兜底)
- `fallback_original_query_zh`(中文字段原文兜底)
|
7bc756c5
tangwang
优化 ES 查询构建
|
144
|
|
bcada818
tangwang
last
|
145
|
这能避免“只有源语种字段查询,且该语种字段在商家索引中稀疏/为空”导致的弱召回问题。
|
7bc756c5
tangwang
优化 ES 查询构建
|
146
|
|
bcada818
tangwang
last
|
147
|
## 7. QueryParser 与 ESBuilder 的职责分工
|
7bc756c5
tangwang
优化 ES 查询构建
|
148
|
|
bcada818
tangwang
last
|
149
150
151
152
153
|
- `QueryParser` 负责“语言计划”与“可用文本”:
- `search_langs`
- `query_text_by_lang`
- `source_in_index_languages`
- `index_languages`
|
e874eb50
tangwang
docs
|
154
|
- `contains_chinese` / `contains_english`
|
bcada818
tangwang
last
|
155
156
157
158
|
- `ESQueryBuilder` 负责“表达式展开”:
- 动态字段组装
- 子句权重分配
- 翻译缺失兜底子句拼接
|
7bc756c5
tangwang
优化 ES 查询构建
|
159
|
|
bcada818
tangwang
last
|
160
|
这种分层让策略调优主要落在配置和 Builder,不破坏 Parser 的职责边界。
|
7bc756c5
tangwang
优化 ES 查询构建
|
161
|
|
c90f80ed
tangwang
相关性优化
|
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
## 8. 融合打分(Rerank + Text + KNN)
当前融合逻辑位于 `search/rerank_client.py`。
### 8.1 文本相关性大分
文本大分由三部分组成:
- `base_query`
- `base_query_trans_*`
- `fallback_original_query_*`
聚合方式:
1. `source_score = base_query`
2. `translation_score = max(base_query_trans_*)`
3. `fallback_score = max(fallback_original_query_*)`
4. 加权:
- `weighted_source = source_score`
- `weighted_translation = 0.8 * translation_score`
- `weighted_fallback = 0.55 * fallback_score`
5. 合成:
- `primary = max(weighted_source, weighted_translation, weighted_fallback)`
- `support = weighted_source + weighted_translation + weighted_fallback - primary`
- `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`
- `text_fallback_score`
- `text_primary_score`
- `text_support_score`
- `knn_score`
- `fused_score`
- `matched_queries`
`debug_info.query_analysis` 还会暴露:
- `query_text_by_lang`
- `search_langs`
- `supplemental_search_langs`
这些字段用于检索效果评估与 bad case 归因。
## 9. 兼容与注意事项
|
7bc756c5
tangwang
优化 ES 查询构建
|
231
|
|
bcada818
tangwang
last
|
232
233
234
235
236
237
238
|
1. 当前文本主链路已移除布尔 AST 分支。
2. 文档中的旧描述(如 `operator: AND` 固定开启)不再适用,当前实现未强制设置该参数。
3. `HanLP` 为可选依赖;不可用时退化到轻量分词,不影响主链路可用性。
4. 若后续扩展到更多语种,请确保:
- mapping 中存在对应 `.<lang>` 字段
- `index_languages` 配置在支持列表内
- 翻译 provider 对目标语种可用
|
7bc756c5
tangwang
优化 ES 查询构建
|
239
|
|
c90f80ed
tangwang
相关性优化
|
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
## 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 查询构建
|
262
|
|
bcada818
tangwang
last
|
263
|
建议在 `tests/` 增加文本策略用例:
|
7bc756c5
tangwang
优化 ES 查询构建
|
264
|
|
bcada818
tangwang
last
|
265
266
267
268
269
|
1. 源语种在索引语言,翻译命中缓存
2. 源语种不在索引语言,翻译部分失败(验证 fallback 子句)
3. 源语种不在索引语言,翻译全部失败(验证多目标 fallback)
4. 自定义 `original_query_fallback_boost_when_translation_missing` 生效
5. 非 `zh/en` 语种字段动态拼接(如 `de/fr/es`)
|
fb973d19
tangwang
configs
|
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
## 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: 黑色高领半高领女士秋冬内搭加绒拼色纯欲设计荷叶边袖内衬上衣
|