Blame view

tests/test_es_query_builder_text_recall_languages.py 16 KB
0536222c   tangwang   query parser优化
1
2
3
  """
  ES text recall: base_query (rewritten @ detected_language) + base_query_trans_*.
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
4
5
6
  Covers translation routing, mixed-script queries (per-clause language fields only),
  and clause naming. Asserts named lexical clause boundaries, combined_fields payloads,
  and per-language target fields (title.{lang}).
0536222c   tangwang   query parser优化
7
8
9
10
11
12
13
  """
  
  from types import SimpleNamespace
  from typing import Any, Dict, List
  
  import numpy as np
  
ceaf6d03   tangwang   召回限定:must条件补充主干词命...
14
  from query.keyword_extractor import KEYWORDS_QUERY_BASE_KEY
0536222c   tangwang   query parser优化
15
16
17
  from search.es_query_builder import ESQueryBuilder
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
18
  def _builder_multilingual_title_only(*, default_language: str = "en") -> ESQueryBuilder:
0536222c   tangwang   query parser优化
19
20
21
22
23
24
25
      """Minimal builder: only title.{lang} for easy field assertions."""
      return ESQueryBuilder(
          match_fields=["title.en^1.0"],
          multilingual_fields=["title"],
          shared_fields=[],
          text_embedding_field="title_embedding",
          default_language=default_language,
0536222c   tangwang   query parser优化
26
27
28
29
30
31
32
          function_score_config=None,
      )
  
  
  def _unwrap_inner_query(es_body: Dict[str, Any]) -> Dict[str, Any]:
      """Navigate bool.must / function_score wrappers to the text recall root."""
      q = es_body.get("query") or {}
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
33
      if "bool" in q and not q["bool"].get("_name") and "must" in q["bool"] and q["bool"]["must"]:
0536222c   tangwang   query parser优化
34
35
36
37
38
39
40
41
42
43
44
45
46
47
          q = q["bool"]["must"][0]
      if "function_score" in q:
          q = q["function_score"]["query"]
      return q
  
  
  def _extract_multi_match_clauses(es_body: Dict[str, Any]) -> List[Dict[str, Any]]:
      inner = _unwrap_inner_query(es_body)
      if "multi_match" in inner:
          return [inner["multi_match"]]
      should = (inner.get("bool") or {}).get("should") or []
      return [c["multi_match"] for c in should if "multi_match" in c]
  
  
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
48
49
50
51
52
53
54
55
  def _extract_named_lexical_clauses(es_body: Dict[str, Any]) -> List[Dict[str, Any]]:
      inner = _unwrap_inner_query(es_body)
      if "bool" in inner and inner["bool"].get("_name"):
          return [inner["bool"]]
      should = (inner.get("bool") or {}).get("should") or []
      return [c["bool"] for c in should if "bool" in c and c["bool"].get("_name")]
  
  
0536222c   tangwang   query parser优化
56
  def _clauses_index(es_body: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
57
      """Map lexical clause _name -> bool query body."""
0536222c   tangwang   query parser优化
58
      out: Dict[str, Dict[str, Any]] = {}
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
59
60
      for clause in _extract_named_lexical_clauses(es_body):
          name = clause.get("_name")
0536222c   tangwang   query parser优化
61
          if name:
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
62
              out[str(name)] = clause
0536222c   tangwang   query parser优化
63
64
65
      return out
  
  
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
66
67
68
  def _combined_fields_clause(clause: Dict[str, Any]) -> Dict[str, Any]:
      return clause["must"][0]["combined_fields"]
  
a3d3fb11   tangwang   加phrase提权
69
  
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
70
71
  def _should_multi_matches(clause: Dict[str, Any]) -> List[Dict[str, Any]]:
      return [item["multi_match"] for item in clause.get("should") or [] if "multi_match" in item]
a3d3fb11   tangwang   加phrase提权
72
  
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
73
74
75
76
77
78
79
  
  def _should_multi_matches_by_type(clause: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
      return {str(mm.get("type") or "best_fields"): mm for mm in _should_multi_matches(clause)}
  
  
  def _title_fields(clause: Dict[str, Any]) -> List[str]:
      fields = _combined_fields_clause(clause).get("fields") or []
0536222c   tangwang   query parser优化
80
81
82
      return [f for f in fields if str(f).startswith("title.")]
  
  
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
83
  def _has_title_lang(clause: Dict[str, Any], lang: str) -> bool:
0536222c   tangwang   query parser优化
84
85
      """True if any field is title.{lang} with optional ^boost suffix."""
      prefix = f"title.{lang}"
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
86
      for f in _combined_fields_clause(clause).get("fields") or []:
0536222c   tangwang   query parser优化
87
88
89
90
91
92
93
94
95
96
97
98
99
          s = str(f)
          if s == prefix or s.startswith(prefix + "^"):
              return True
      return False
  
  
  def _build(
      qb: ESQueryBuilder,
      *,
      query_text: str,
      rewritten: str,
      detected_language: str,
      translations: Dict[str, str],
0536222c   tangwang   query parser优化
100
101
102
103
104
  ) -> Dict[str, Any]:
      parsed = SimpleNamespace(
          rewritten_query=rewritten,
          detected_language=detected_language,
          translations=dict(translations),
0536222c   tangwang   query parser优化
105
106
107
108
109
      )
      return qb.build_query(
          query_text=query_text,
          parsed_query=parsed,
          enable_knn=False,
0536222c   tangwang   query parser优化
110
111
112
113
114
115
116
117
118
119
120
121
122
123
      )
  
  
  # --- 检测语言在 index_languages 内:主召回 + 翻译补召回 ---
  
  
  def test_zh_query_index_zh_en_includes_base_zh_and_trans_en():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="连衣裙",
          rewritten="连衣裙",
          detected_language="zh",
          translations={"en": "dress"},
0536222c   tangwang   query parser优化
124
125
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
126
127
      assert set(idx) == {"base_query", "base_query_trans_en"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "连衣裙"
0536222c   tangwang   query parser优化
128
      assert "title.zh" in _title_fields(idx["base_query"])
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
129
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "dress"
0536222c   tangwang   query parser优化
130
131
132
      assert "title.en" in _title_fields(idx["base_query_trans_en"])
  
  
ceaf6d03   tangwang   召回限定:must条件补充主干词命...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  def test_keywords_combined_fields_second_must_same_fields_and_50pct():
      """When ParsedQuery.keywords_queries is set, must includes a second combined_fields."""
      qb = _builder_multilingual_title_only(default_language="en")
      parsed = SimpleNamespace(
          rewritten_query="连衣裙",
          detected_language="zh",
          translations={"en": "red dress"},
          keywords_queries={KEYWORDS_QUERY_BASE_KEY: "连衣 裙", "en": "dress"},
      )
      q = qb.build_query(query_text="连衣裙", parsed_query=parsed, enable_knn=False)
      idx = _clauses_index(q)
      base = idx["base_query"]
      assert len(base["must"]) == 2
      assert base["must"][0]["combined_fields"]["query"] == "连衣裙"
      assert base["must"][1]["combined_fields"]["query"] == "连衣 裙"
      assert base["must"][1]["combined_fields"]["minimum_should_match"] == "50%"
      assert base["must"][1]["combined_fields"]["fields"] == base["must"][0]["combined_fields"]["fields"]
      trans = idx["base_query_trans_en"]
      assert len(trans["must"]) == 2
      assert trans["must"][1]["combined_fields"]["query"] == "dress"
      assert trans["must"][1]["combined_fields"]["minimum_should_match"] == "50%"
  
  
0536222c   tangwang   query parser优化
156
157
158
159
160
161
162
163
  def test_en_query_index_zh_en_includes_base_en_and_trans_zh():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="dress",
          rewritten="dress",
          detected_language="en",
          translations={"zh": "连衣裙"},
0536222c   tangwang   query parser优化
164
165
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
166
167
      assert set(idx) == {"base_query", "base_query_trans_zh"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "dress"
0536222c   tangwang   query parser优化
168
      assert "title.en" in _title_fields(idx["base_query"])
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
169
      assert _combined_fields_clause(idx["base_query_trans_zh"])["query"] == "连衣裙"
0536222c   tangwang   query parser优化
170
171
172
173
174
175
176
177
178
179
180
      assert "title.zh" in _title_fields(idx["base_query_trans_zh"])
  
  
  def test_de_query_index_de_en_fr_includes_base_and_two_translations():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="kleid",
          rewritten="kleid",
          detected_language="de",
          translations={"en": "dress", "fr": "robe"},
0536222c   tangwang   query parser优化
181
182
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
183
184
      assert set(idx) == {"base_query", "base_query_trans_en", "base_query_trans_fr"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "kleid"
0536222c   tangwang   query parser优化
185
      assert "title.de" in _title_fields(idx["base_query"])
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
186
187
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "dress"
      assert _combined_fields_clause(idx["base_query_trans_fr"])["query"] == "robe"
0536222c   tangwang   query parser优化
188
189
190
191
192
193
194
195
196
197
198
199
200
  
  
  # --- 检测语言不在 index_languages:仍有 base(弱)+ 翻译(强) ---
  
  
  def test_de_query_index_only_en_zh_base_on_de_translations_on_target_fields():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="schuh",
          rewritten="schuh",
          detected_language="de",
          translations={"en": "shoe", "zh": "鞋"},
0536222c   tangwang   query parser优化
201
202
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
203
204
      assert set(idx) == {"base_query", "base_query_trans_en", "base_query_trans_zh"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "schuh"
0536222c   tangwang   query parser优化
205
206
      assert "title.de" in _title_fields(idx["base_query"])
      assert "boost" not in idx["base_query"]
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
207
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "shoe"
0536222c   tangwang   query parser优化
208
      assert idx["base_query_trans_en"]["boost"] == qb.translation_boost
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
209
      assert _combined_fields_clause(idx["base_query_trans_zh"])["query"] == "鞋"
0536222c   tangwang   query parser优化
210
211
212
      assert idx["base_query_trans_zh"]["boost"] == qb.translation_boost
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
213
  # --- 中英混写:base 打在检测语种字段;翻译子句打在译文语种字段 ---
0536222c   tangwang   query parser优化
214
215
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
216
  def test_mixed_zh_detected_base_clause_zh_fields_only_with_en_translation():
0536222c   tangwang   query parser优化
217
218
219
220
221
222
223
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="红色 dress",
          rewritten="红色 dress",
          detected_language="zh",
          translations={"en": "red dress"},
0536222c   tangwang   query parser优化
224
225
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
226
227
      assert set(idx) == {"base_query", "base_query_trans_en"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "红色 dress"
35da3813   tangwang   中英混写query的优化逻辑,不适...
228
      assert _has_title_lang(idx["base_query"], "zh") and not _has_title_lang(idx["base_query"], "en")
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
229
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "red dress"
0536222c   tangwang   query parser优化
230
231
232
      assert _has_title_lang(idx["base_query_trans_en"], "en")
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
233
  def test_mixed_en_detected_base_clause_en_fields_only_with_zh_translation():
0536222c   tangwang   query parser优化
234
235
236
237
238
239
240
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="nike 运动鞋",
          rewritten="nike 运动鞋",
          detected_language="en",
          translations={"zh": "耐克运动鞋"},
0536222c   tangwang   query parser优化
241
242
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
243
244
      assert set(idx) == {"base_query", "base_query_trans_zh"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "nike 运动鞋"
35da3813   tangwang   中英混写query的优化逻辑,不适...
245
      assert _has_title_lang(idx["base_query"], "en") and not _has_title_lang(idx["base_query"], "zh")
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
246
      assert _combined_fields_clause(idx["base_query_trans_zh"])["query"] == "耐克运动鞋"
0536222c   tangwang   query parser优化
247
248
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
249
  def test_zh_query_no_translations_only_zh_fields():
0536222c   tangwang   query parser优化
250
251
252
253
254
255
256
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="法式 dress",
          rewritten="法式 dress",
          detected_language="zh",
          translations={},
0536222c   tangwang   query parser优化
257
258
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
259
      assert set(idx) == {"base_query"}
0536222c   tangwang   query parser优化
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
      bases = {f.split("^", 1)[0] for f in _title_fields(idx["base_query"])}
      assert bases == {"title.zh"}
  
  
  # --- 去重:与 base 同语言同文本的翻译项跳过 ---
  
  
  def test_skips_translation_when_same_lang_and_same_text_as_base():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="NIKE",
          rewritten="NIKE",
          detected_language="en",
          translations={"en": "NIKE", "zh": "耐克"},
0536222c   tangwang   query parser优化
275
276
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
277
      assert set(idx) == {"base_query", "base_query_trans_zh"}
0536222c   tangwang   query parser优化
278
279
280
281
282
283
284
285
286
287
  
  
  def test_keeps_translation_when_same_text_but_different_lang_than_base():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="NIKE",
          rewritten="NIKE",
          detected_language="en",
          translations={"zh": "NIKE"},
0536222c   tangwang   query parser优化
288
289
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
290
291
      assert set(idx) == {"base_query", "base_query_trans_zh"}
      assert _combined_fields_clause(idx["base_query_trans_zh"])["query"] == "NIKE"
0536222c   tangwang   query parser优化
292
293
294
295
296
297
298
299
300
301
302
303
304
  
  
  # --- 翻译 key 规范化、空翻译跳过 ---
  
  
  def test_translation_language_key_is_normalized_case_insensitive():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="dress",
          rewritten="dress",
          detected_language="en",
          translations={"ZH": "连衣裙"},
0536222c   tangwang   query parser优化
305
306
307
      )
      idx = _clauses_index(q)
      assert "base_query_trans_zh" in idx
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
308
      assert _combined_fields_clause(idx["base_query_trans_zh"])["query"] == "连衣裙"
0536222c   tangwang   query parser优化
309
310
311
312
313
314
315
316
317
318
  
  
  def test_empty_translation_value_is_skipped():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="dress",
          rewritten="dress",
          detected_language="en",
          translations={"zh": "  ", "fr": "robe"},
0536222c   tangwang   query parser优化
319
320
321
322
323
324
      )
      idx = _clauses_index(q)
      assert "base_query_trans_zh" not in idx
      assert "base_query_trans_fr" in idx
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
325
  # --- base 子句无 bool.boost;翻译子句带 translation_boost;phrase should 继承 phrase_match_boost ---
0536222c   tangwang   query parser优化
326
327
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
328
  def test_de_base_and_en_translation_phrase_boosts():
0536222c   tangwang   query parser优化
329
330
331
332
333
334
335
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="x",
          rewritten="x",
          detected_language="de",
          translations={"en": "y"},
0536222c   tangwang   query parser优化
336
337
338
339
      )
      idx = _clauses_index(q)
      assert "boost" not in idx["base_query"]
      assert idx["base_query_trans_en"]["boost"] == qb.translation_boost
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
340
341
342
343
      base_should = _should_multi_matches_by_type(idx["base_query"])
      trans_should = _should_multi_matches_by_type(idx["base_query_trans_en"])
      assert base_should["phrase"]["boost"] == qb.phrase_match_boost
      assert trans_should["phrase"]["boost"] == qb.phrase_match_boost
0536222c   tangwang   query parser优化
344
345
346
347
348
349
350
351
352
353
354
355
356
  
  
  # --- 无翻译:仅 base_query ---
  
  
  def test_no_translations_only_base_query():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="hello",
          rewritten="hello",
          detected_language="en",
          translations={},
0536222c   tangwang   query parser优化
357
358
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
359
      assert set(idx) == {"base_query"}
0536222c   tangwang   query parser优化
360
361
362
363
364
365
366
367
368
369
370
  
  
  # --- 与 KNN 同存时仍能解析文本子句(顶层 knn 不影响 query 内结构) ---
  
  
  def test_text_clauses_present_alongside_knn():
      qb = _builder_multilingual_title_only(default_language="en")
      parsed = SimpleNamespace(
          rewritten_query="dress",
          detected_language="en",
          translations={"zh": "连衣裙"},
0536222c   tangwang   query parser优化
371
372
373
374
375
376
      )
      q = qb.build_query(
          query_text="dress",
          query_vector=np.array([0.1, 0.2, 0.3], dtype=np.float32),
          parsed_query=parsed,
          enable_knn=True,
0536222c   tangwang   query parser优化
377
      )
ed13851c   tangwang   图片文本两个knn召回相关参数配置
378
379
380
381
      qr = q["query"]
      if "function_score" in qr:
          qr = qr["function_score"]["query"]
      assert any("knn" in c for c in qr["bool"]["should"])
0536222c   tangwang   query parser优化
382
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
383
      assert set(idx) == {"base_query", "base_query_trans_zh"}
0536222c   tangwang   query parser优化
384
385
386
387
388
389
390
391
392
  
  
  def test_detected_language_unknown_falls_back_to_default_language():
      """与 LanguageDetector 失败时 QueryConfig.default_language 行为对齐。"""
      qb = _builder_multilingual_title_only(default_language="en")
      parsed = SimpleNamespace(
          rewritten_query="shirt",
          detected_language="unknown",
          translations={"zh": "衬衫"},
0536222c   tangwang   query parser优化
393
394
395
396
397
      )
      q = qb.build_query(
          query_text="shirt",
          parsed_query=parsed,
          enable_knn=False,
0536222c   tangwang   query parser优化
398
399
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
400
401
      assert set(idx) == {"base_query", "base_query_trans_zh"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "shirt"
0536222c   tangwang   query parser优化
402
403
404
405
406
407
408
409
410
411
412
      assert _has_title_lang(idx["base_query"], "en")
  
  
  def test_ru_query_index_ru_en_includes_base_ru_and_trans_en():
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="платье",
          rewritten="платье",
          detected_language="ru",
          translations={"en": "dress"},
0536222c   tangwang   query parser优化
413
414
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
415
416
      assert set(idx) == {"base_query", "base_query_trans_en"}
      assert _combined_fields_clause(idx["base_query"])["query"] == "платье"
0536222c   tangwang   query parser优化
417
      assert _has_title_lang(idx["base_query"], "ru")
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
418
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "dress"
0536222c   tangwang   query parser优化
419
420
  
  
35da3813   tangwang   中英混写query的优化逻辑,不适...
421
422
  def test_translation_generates_clause_for_any_target_lang_key():
      """translations 里非空的每个语种键都会生成对应 base_query_trans_* 子句。"""
0536222c   tangwang   query parser优化
423
424
425
426
427
428
429
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text="dress",
          rewritten="dress",
          detected_language="en",
          translations={"zh": "连衣裙", "de": "Kleid"},
0536222c   tangwang   query parser优化
430
431
432
      )
      idx = _clauses_index(q)
      assert "base_query_trans_de" in idx
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
433
      assert _combined_fields_clause(idx["base_query_trans_de"])["query"] == "Kleid"
0536222c   tangwang   query parser优化
434
435
436
437
438
439
440
441
442
443
444
445
      assert _has_title_lang(idx["base_query_trans_de"], "de")
  
  
  def test_mixed_detected_zh_rewrite_differs_from_query_text_uses_rewritten_in_base():
      """base_query 始终用 rewritten_query,而非仅 query_text。"""
      qb = _builder_multilingual_title_only(default_language="en")
      q = _build(
          qb,
          query_text=" 红色 ",
          rewritten="红色连衣裙",
          detected_language="zh",
          translations={"en": "red dress"},
0536222c   tangwang   query parser优化
446
447
      )
      idx = _clauses_index(q)
e756b18e   tangwang   重构了文本召回构建器,现在每个 b...
448
449
      assert _combined_fields_clause(idx["base_query"])["query"] == "红色连衣裙"
      assert _combined_fields_clause(idx["base_query_trans_en"])["query"] == "red dress"