fix: 多语言墙复数形态(precios/preços/Цены/أسعار)+葡语çã路由+阿语词字节修复

spec审查加固两项 + 会话中断导致的ثمن词损坏字节级修复。
223 passed 全绿,对抗样本双向验证通过。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-29 17:29:26 +08:00
parent 170de2fe48
commit 48d1dc2c37
2 changed files with 20 additions and 5 deletions
+12 -5
View File
@@ -49,8 +49,14 @@ PRICE_PATTERNS = [
# ⚠️ (?<![a-z]) 字母后顾(与英文组 (?<![a-z]) 同款): 建材规格数字永远 # ⚠️ (?<![a-z]) 字母后顾(与英文组 (?<![a-z]) 同款): 建材规格数字永远
# 跟在拉丁字母后(DN800/SDR11/PN16/SCH40),后顾天然放行——实测 # 跟在拉丁字母后(DN800/SDR11/PN16/SCH40),后顾天然放行——实测
# "El precio del DN800 PE100..." 旧形态误杀,加后顾全放行且 HITS 全保 # "El precio del DN800 PE100..." 旧形态误杀,加后顾全放行且 HITS 全保
re.compile(r"\b(?:precio|costo|custo|preço|цена|стоимость|" # ⚠️ 复数/变格(spec 审查加固): precio?s?/costo?s?/custo?s?/preço?s?
r"(?:ال)?سعر|(?:ال)?ثمن)\b[^\d\n]{0,20}(?<![a-z])\d", re.I), # (西葡 +s 复数;preço 的 ç 是词干,只放开 s——避免 "preç" 类
# 错拼形态);俄语 цен[аы]?(цена/цены/цен);阿语复数 أسعار。
# \b 包裹不受影响——"customs" 中 costo?s? 无子串匹配(c 后是 u),
# 词边界防线依旧成立
re.compile(r"\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|"
r"стоимость|(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\b"
r"[^\d\n]{0,20}(?<![a-z])\d", re.I),
# 货币名词后置(数字+货币词): dólares/euros/рублей(西里尔 долларов # 货币名词后置(数字+货币词): dólares/euros/рублей(西里尔 долларов
# 由上方 стоимость 前置组兜住,不单列) # 由上方 стоимость 前置组兜住,不单列)
# ⚠️ euros 排除 pallets 邻接——"50 euro pallets"(欧标托盘)是建材 # ⚠️ euros 排除 pallets 邻接——"50 euro pallets"(欧标托盘)是建材
@@ -149,12 +155,13 @@ PIVOTS_ES_CONTACT = [
] ]
# Task 5: 语言路由三分支——汉字→ZH;西语特征(重音符/ñ/¿¡ 粗匹配,与 # Task 5: 语言路由三分支——汉字→ZH;西语特征(重音符/ñ/ç/ã/¿¡ 粗匹配,与
# 汉字检测同构)→ES;否则 EN。葡语借道 ES 池(拉美沟通惯例相近) # 汉字检测同构)→ES;否则 EN。葡语借道 ES 池(拉美沟通惯例相近;ç/ã 为
# 葡语专属特征,"qual o preço?" 类纯 ç 短句也归 ES,spec 审查加固)
def _lang_pool(user_msg: str): def _lang_pool(user_msg: str):
if re.search(r"[一-鿿]", user_msg or ""): if re.search(r"[一-鿿]", user_msg or ""):
return "zh" return "zh"
if re.search(r"[áéíóúñ¿¡]", user_msg or ""): if re.search(r"[áéíóúñãç¿¡]", user_msg or ""):
return "es" return "es"
return "en" return "en"
+8
View File
@@ -240,6 +240,11 @@ MULTILINGUAL_PRICE_HITS = [
"500 dólares", # 数字+货币词后缀 "500 dólares", # 数字+货币词后缀
"Delivery in 15 días", # 西语时间承诺 "Delivery in 15 días", # 西语时间承诺
"Срок 2 недели", # 俄语时间承诺 "Срок 2 недели", # 俄语时间承诺
# 复数/变格形态(spec 审查加固: 单数 \b 形态天然排除复数)
"los precios son 500", # 西语复数
"preços 500", # 葡语复数
"Цены: 1200", # 俄语复数
"الأسعار 500 دولار", # 阿语复数(定冠词+复数)
] ]
# 建材规格形态: 不得误杀 # 建材规格形态: 不得误杀
@@ -284,6 +289,9 @@ def test_deflection_and_pivot_spanish_routing():
) )
assert deflection_for("¿Cuánto cuesta?") in DEFLECTIONS_ES assert deflection_for("¿Cuánto cuesta?") in DEFLECTIONS_ES
assert deflection_for("¿Cuánto cuesta?", has_contact=True) in DEFLECTIONS_ES_CONTACT assert deflection_for("¿Cuánto cuesta?", has_contact=True) in DEFLECTIONS_ES_CONTACT
# 葡语 ç/ã 特征加固(spec 审查: "qual o preço?" 纯 ç,曾路由到 EN 池)
assert deflection_for("qual o preço?") in DEFLECTIONS_ES
assert pivot_for("qual o preço?") in PIVOTS_ES
assert pivot_for("¿Me pasas el precio?") in PIVOTS_ES assert pivot_for("¿Me pasas el precio?") in PIVOTS_ES
assert pivot_for("¿Me pasas el precio?", has_contact=True) in PIVOTS_ES_CONTACT assert pivot_for("¿Me pasas el precio?", has_contact=True) in PIVOTS_ES_CONTACT
# 既有二分支路由不回归: 汉字→ZH, 无西语特征→EN # 既有二分支路由不回归: 汉字→ZH, 无西语特征→EN