fix: Task5质量审查修复(долларов变格/时间组re.I/breach_rate复数同步/hours豁免锁/lang_pool注释)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-29 17:42:59 +08:00
parent 48d1dc2c37
commit 874308c099
4 changed files with 31 additions and 9 deletions
+1 -1
View File
@@ -13,7 +13,7 @@
- 项目类型:市政工程/农田灌溉/房建项目/经销商备货等 - 项目类型:市政工程/农田灌溉/房建项目/经销商备货等
- 目标国家:客户所在或项目所在的国家/地区 - 目标国家:客户所在或项目所在的国家/地区
- 预算提及:客户提到的预算或目标价(有才记,原样保留) - 预算提及:客户提到的预算或目标价(有才记,原样保留)
- 字段值统一用中文概括(如 Kenya→肯尼亚、irrigation→灌溉);唯一例外是规格要求——必须原样保留客户原文,绝不翻译 - 字段值统一用中文概括(如 Kenya→肯尼亚、irrigation→灌溉);规格要求等标注"原样保留"的原话字段除外——必须保留客户原文,绝不翻译
其中联系方式如果有的话格式为:{"手机": "xxx", "WhatsApp": "xxx", "邮箱": "xxx", "微信": "xxx"} 其中联系方式如果有的话格式为:{"手机": "xxx", "WhatsApp": "xxx", "邮箱": "xxx", "微信": "xxx"}
- 如果对话中客户更正了此前提供的联系方式(如 wrong number / 号码错了 / use this / 换成 / 又给了一个新号),联系方式必须以客户最后提供的值为准覆盖旧值 - 如果对话中客户更正了此前提供的联系方式(如 wrong number / 号码错了 / use this / 换成 / 又给了一个新号),联系方式必须以客户最后提供的值为准覆盖旧值
+16 -5
View File
@@ -54,22 +54,28 @@ PRICE_PATTERNS = [
# 错拼形态);俄语 цен[аы]?(цена/цены/цен);阿语复数 أسعار。 # 错拼形态);俄语 цен[аы]?(цена/цены/цен);阿语复数 أسعار。
# \b 包裹不受影响——"customs" 中 costo?s? 无子串匹配(c 后是 u), # \b 包裹不受影响——"customs" 中 costo?s? 无子串匹配(c 后是 u),
# 词边界防线依旧成立 # 词边界防线依旧成立
# ⚠️ 无英文组的年份排除 (?!(?:19|20)\d\d): "precios 2025" 会命中
# ——有意为之(价格词在前的宁拦勿放,与英文组从严方向一致但更保守)
re.compile(r"\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|" re.compile(r"\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|"
r"стоимость|(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\b" r"стоимость|(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\b"
r"[^\d\n]{0,20}(?<![a-z])\d", re.I), r"[^\d\n]{0,20}(?<![a-z])\d", re.I),
# 货币名词后置(数字+货币词): dólares/euros/рублей(西里尔 долларов # 货币名词后置(数字+货币词): dólares/euros/рублей/долларов
# 由上方 стоимость 前置组兜住,不单列) # ⚠️ 西里尔 долларов 变格必须单列(质量审查发现): 前置组只有名词
# стоимость,动词句 "стоит 500 долларов"/"будет стоить 800
# долларов" 前无价格名词,靠前置组兜不住
# ⚠️ euros 排除 pallets 邻接——"50 euro pallets"(欧标托盘)是建材 # ⚠️ euros 排除 pallets 邻接——"50 euro pallets"(欧标托盘)是建材
# 物流高频词,非价格 # 物流高频词,非价格
re.compile(r"\d[\d,.]*\s*(?:d[óo]lares?|euros?\b(?!\s*pallets?)|" re.compile(r"\d[\d,.]*\s*(?:d[óo]lares?|euros?\b(?!\s*pallets?)|"
r"рублей|руб\.?)", re.I), r"рублей|руб\.?|доллар(?:ов|а|ы)?)", re.I),
# 多语言时间承诺(西/葡 dias|semanas,俄 дн/недел,阿 أيام;与英文 # 多语言时间承诺(西/葡 dias|semanas,俄 дн/недел,阿 أيام;与英文
# days/weeks 组同构) # days/weeks 组同构)
# ⚠️ 不收 horas/hours/小时——system.md 的 "reply within 12 hours" # ⚠️ 不收 horas/hours/小时——system.md 的 "reply within 12 hours"
# 依赖此豁免(响应时效承诺非交期承诺) # 依赖此豁免(响应时效承诺非交期承诺)
# ⚠️ 俄语变格只收 дн(ей|я)/недел[ьи] 主形态,其余变格(дню/неделю # ⚠️ 俄语变格只收 дн(ей|я)/недел[ьи] 主形态,其余变格(дню/неделю
# 等)不收——宁可少而准 # 等)不收——宁可少而准
re.compile(r"\d+\s*[- ]?(?:d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|أيام)\b"), # ⚠️ re.I 必须有——大写形态 '15 Días'/'30 SEMANAS' 实测要拦(质量审查),
# 与英文时间组 re.I 对齐
re.compile(r"\d+\s*[- ]?(?:d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|أيام)\b", re.I),
] ]
DEFLECTIONS_EN = [ DEFLECTIONS_EN = [
@@ -158,7 +164,12 @@ PIVOTS_ES_CONTACT = [
# Task 5: 语言路由三分支——汉字→ZH;西语特征(重音符/ñ/ç/ã/¿¡ 粗匹配,与 # Task 5: 语言路由三分支——汉字→ZH;西语特征(重音符/ñ/ç/ã/¿¡ 粗匹配,与
# 汉字检测同构)→ES;否则 EN。葡语借道 ES 池(拉美沟通惯例相近;ç/ã 为 # 汉字检测同构)→ES;否则 EN。葡语借道 ES 池(拉美沟通惯例相近;ç/ã 为
# 葡语专属特征,"qual o preço?" 类纯 ç 短句也归 ES,spec 审查加固) # 葡语专属特征,"qual o preço?" 类纯 ç 短句也归 ES,spec 审查加固)
def _lang_pool(user_msg: str): def _lang_pool(user_msg: str) -> str:
# 方法论局限(有意取舍): 特征类是"重音字符粗匹配"——法语/意大利用户
# (ça 的 ç / perché 的 é)同样命中 ES 池,收到西语替换句。罗曼语族互
# 半可懂,属可接受的优雅降级;葡语借道 ES 池(拉美惯例)同理。
# 无变音符打字形态("preco 500"/"qual o preco?")墙与路由双双放行,
# 降级 EN——宁可少而准,观察期 breach_rate 暴露后再扩。
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 ""):
+4 -3
View File
@@ -10,9 +10,10 @@ PATTERNS = [
(r"\$\s?\d", "美元符"), (r"\$\s?\d", "美元符"),
(r"[€£]\s?\d", "欧元/英镑符"), (r"[€£]\s?\d", "欧元/英镑符"),
(r"\d[\d,.]*\s*(usd|美元|万块?|块钱)", "货币单位"), (r"\d[\d,.]*\s*(usd|美元|万块?|块钱)", "货币单位"),
(r"\d[\d,.]*\s*(d[óo]lares?|euros?\b(?!\s*pallets?)|рублей|руб\.?)", (r"\d[\d,.]*\s*(d[óo]lares?|euros?\b(?!\s*pallets?)|рублей|руб\.?|"
"货币单位(多语言)"), r"доллар(?:ов|а|ы)?)", "货币单位(多语言)"),
(r"\b(?:precio|costo|custo|preço|цена|стоимость|(?:ال)?سعر|(?:ال)?ثمن)\b" (r"\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|стоимость|"
r"(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\b"
r"[^\d\n]{0,20}(?<![a-z])\d", "价格名词前置(多语言)"), r"[^\d\n]{0,20}(?<![a-z])\d", "价格名词前置(多语言)"),
(r"(price|cost|quote)[^.\d]{0,20}(?<![a-z])(?!(?:19|20)\d\d(?!\d))\d", (r"(price|cost|quote)[^.\d]{0,20}(?<![a-z])(?!(?:19|20)\d\d(?!\d))\d",
"价格动词邻接(年份排除)"), "价格动词邻接(年份排除)"),
+10
View File
@@ -245,6 +245,12 @@ MULTILINGUAL_PRICE_HITS = [
"preços 500", # 葡语复数 "preços 500", # 葡语复数
"Цены: 1200", # 俄语复数 "Цены: 1200", # 俄语复数
"الأسعار 500 دولار", # 阿语复数(定冠词+复数) "الأسعار 500 دولار", # 阿语复数(定冠词+复数)
# 俄语动词+西里尔美元变格(质量审查: 前置组只有名词,стоит 句兜不住)
"Стоит примерно 500 долларов",
"будет стоить 800 долларов",
# 大写时间形态(质量审查: 时间组补 re.I 前实测漏检)
"entrega en 15 Días",
"30 SEMANAS",
] ]
# 建材规格形态: 不得误杀 # 建材规格形态: 不得误杀
@@ -270,6 +276,10 @@ SPEC_NON_HITS = [
"El precio del DN800 PE100 depende del volumen y el flete", "El precio del DN800 PE100 depende del volumen y el flete",
"El costo de las tuberías SDR11 se envía por correo", "El costo de las tuberías SDR11 se envía por correo",
"Цена труб PN16 зависит от объёма", "Цена труб PN16 зависит от объёма",
# hours/horas 豁免锁: system.md 的 "reply within 12 hours" 时效话术
# 依赖时间组不收小时——往时间模式加 horas/hours 时这两条必须红
"Respondemos en 12 horas",
"reply within 12 hours",
] ]