Files
ai-kefu-admin/seed_profiles/jiancai/wall.json
T
浅念 bc903a273e feat: 词表数据化——AST 提取脚本 + wall.json + 编译器 + boundary/conversation 数据源切换(等价回归全绿)
- scripts/extract_config.py: AST 解析两老项目源码取常量(不 import 源模块),
  生成 seed_profiles/<slug>/{wall.json, brand_values.json, prompts/};幂等可重跑
- app/engine/wall_schema.py: compile_wall(json)→CompiledWall,坏结构/坏 regex
  编译期显性失败(WallConfigError 含字段路径)
- boundary_filter/conversation: 墙词表/话术数据源切换为 DEFAULT_WALL
  (jiancai 出厂 seed),函数逻辑不动、常量名保留为 wall 视图(既有测试零修改);
  wall 数据化新增 pivots/pivots_contact/zero_number/reask_patterns 字段
- 脆锚点迁移: test_inline_prohibitions 断言对象从 conversation.py 源码改为
  wall.json 数据文件,语义等价(唯一允许的测试修改)
- 回归: 322 既有全绿 + 10 新增 wall_schema 测试 = 332;提取脚本两遍无 diff

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-12 17:31:57 +08:00

232 lines
17 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"price_patterns": [
"\\$\\s?\\d",
{
"pattern": "\\d[\\d,.]*\\s*(usd\\b|美元|块钱|万块?(?!\\s*(公里|km)))",
"flags": "i"
},
{
"pattern": "\\d[\\d,.]*\\s?k\\b(?!\\s*(km|kilometers?|kilometres?|miles?|mi\\b|公里))",
"flags": "i"
},
{
"pattern": "(price|cost|quote)[^.\\d]{0,20}(?<![a-z])(?!(?:19|20)\\d\\d(?!\\d))\\d",
"flags": "i"
},
{
"pattern": "\\d+\\s*[- ]?(day|week|month)s?\\b",
"flags": "i",
"comment": "# 时间承诺: 去掉 warranty 豁免(政策变更 2026-09-10——保修期限是编造的\n# 公司政策承诺,不再白名单)"
},
{
"pattern": "\\d+\\s*years?\\b[^.!?]{0,15}warranty",
"flags": "i",
"comment": "# 年限保修定向(双向): year 不能进时间模式(使用年限 \"under 5 years old\" 会误杀),\n# 只收 数字+年 与 warranty/质保/保修 的组合(含倒装\"质保3年\"/\"warranty of 8 years\")"
},
{
"pattern": "warranty\\s*(?:of|for|:)?\\s*\\d+\\s*years?\\b",
"flags": "i"
},
"\\d+\\s*年[^。!?]{0,8}(?:质保|保修)",
"(?:质保|保修)[^。!?]{0,8}\\d+\\s*年",
{
"pattern": "\\d+\\s*(?:天|周|个月)",
"comment": "# 中文时限承诺: 天/周/个月(年不收——裸 \"2024年\" 是年份/项目日期,\n# 带质保/保修的年限由上方定向组收)"
},
{
"pattern": "(budget|预算)[^\\d\\n]{0,12}\\d",
"flags": "i",
"comment": "# 裸预算复述(F3,方案B旗舰形态——冒烟 6/6 破防即此形,原模式完全漏检)"
},
"(两|三|四|五|六|七|八|九|十)\\s*万(?!\\s*(公里|km))",
{
"pattern": "(down\\s+payment|monthly\\s+payment|首付|月供)[^\\d\\n]{0,10}\\d",
"flags": "i",
"comment": "# 金融裸数(F4)"
},
{
"pattern": "[€£]\\s?\\d",
"comment": "# ---- 多语言墙(建材市场: 欧/英/南美/俄语区/中东) ----\n# 货币符号: €/£(参考项目只有 $)"
},
{
"pattern": "\\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|стоимость|(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\\b[^\\d\\n]{0,20}(?<![a-z])\\d",
"flags": "i",
"comment": "# 价格名词前置(西/葡/俄/阿): 词后 0-20 非数字字符内出现数字\n# ⚠️ 拉丁词必须加 \\b 词边界——custo 是英文 customs 的子串,外贸高频,\n# \"customs paperwork for 20ft\" 会被误杀(Task 3 质量审查发现)\n# ⚠️ 阿语定冠词 ال 与词连写(السعر): 词首 \\b 落在 ل|س 之间(两者皆 \\w)\n# 不成立,备选须收 (?:ال)? 形态——裸 \\bسعر\\b 实测漏检 \"السعر 500 دولار\"\n# ⚠️ (?<![a-z]) 字母后顾(与英文组 (?<![a-z]) 同款): 建材规格数字永远\n# 跟在拉丁字母后(DN800/SDR11/PN16/SCH40),后顾天然放行——实测\n# \"El precio del DN800 PE100...\" 旧形态误杀,加后顾全放行且 HITS 全保\n# ⚠️ 复数/变格(spec 审查加固): precio?s?/costo?s?/custo?s?/preço?s?\n# (西葡 +s 复数;preço 的 ç 是词干,只放开 s——避免 \"preç\" 类\n# 错拼形态);俄语 цен[аы]?(цена/цены/цен);阿语复数 أسعار。\n# \\b 包裹不受影响——\"customs\" 中 costo?s? 无子串匹配(c 后是 u),\n# 词边界防线依旧成立\n# ⚠️ 无英文组的年份排除 (?!(?:19|20)\\d\\d): \"precios 2025\" 会命中\n# ——有意为之(价格词在前的宁拦勿放,与英文组从严方向一致但更保守)"
},
{
"pattern": "\\d[\\d,.]*\\s*(?:d[óo]lares?|euros?\\b(?!\\s*pallets?)|рублей|руб\\.?|доллар(?:ов|а|ы)?)",
"flags": "i",
"comment": "# 货币名词后置(数字+货币词): dólares/euros/рублей/долларов\n# ⚠️ 西里尔 долларов 变格必须单列(质量审查发现): 前置组只有名词\n# стоимость,动词句 \"стоит 500 долларов\"/\"будет стоить 800\n# долларов\" 前无价格名词,靠前置组兜不住\n# ⚠️ euros 排除 pallets 邻接——\"50 euro pallets\"(欧标托盘)是建材\n# 物流高频词,非价格"
},
{
"pattern": "\\d+\\s*[- ]?(?:d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|أيام)\\b",
"flags": "i",
"comment": "# 多语言时间承诺(西/葡 dias|semanas,俄 дн/недел,阿 أيام;与英文\n# days/weeks 组同构)\n# ⚠️ 不收 horas/hours/小时——system.md 的 \"reply within 12 hours\"\n# 依赖此豁免(响应时效承诺非交期承诺)\n# ⚠️ 俄语变格只收 дн(ей|я)/недел[ьи] 主形态,其余变格(дню/неделю\n# 等)不收——宁可少而准\n# ⚠️ re.I 必须有——大写形态 '15 Días'/'30 SEMANAS' 实测要拦(质量审查),\n# 与英文时间组 re.I 对齐"
}
],
"deflections": {
"en": [
"Prices vary a lot by config and shipping — our manager will prepare an exact quote for you. What's your WhatsApp or email?",
"For an exact price our manager needs your config and destination — drop your WhatsApp and you'll have the quote today.",
"I'd rather give you an exact number than a rough guess — leave your WhatsApp and our manager will send it over."
],
"zh": [
"价格要看配置和目的地,客户经理会给你准确报价——留个WhatsApp或邮箱?",
"我让客户经理按你的情况出准确报价,留个联系方式,今天就能发你。"
],
"es": [
"El precio exacto depende de la especificación y el flete — nuestro gerente te lo prepara. ¿Me dejas tu WhatsApp o correo?",
"Para un precio exacto, nuestro gerente necesita tu especificación y destino — déjame tu WhatsApp y lo tienes hoy.",
"Prefiero darte una cifra exacta y no un estimado — déjanos tu WhatsApp y nuestro gerente te lo envía."
]
},
"deflections_contact": {
"en": [
"Our manager will send the exact quote to your WhatsApp shortly. Anything else about our pipes?"
],
"zh": [
"客户经理稍后会把准确报价发到你的 WhatsApp。还想了解什么管道产品?"
],
"es": [
"Nuestro gerente te enviará el precio exacto a tu WhatsApp en breve. ¿Algo más sobre nuestras tuberías?"
]
},
"pivots": {
"en": [
"Actually, for the exact price — what's your WhatsApp? Our manager will send it over."
],
"zh": [
"具体的报价,客户经理会发给你——留个WhatsApp或邮箱?"
],
"es": [
"Para el precio exacto — ¿cuál es tu WhatsApp? Nuestro gerente te lo envía."
]
},
"pivots_contact": {
"en": [
"Our manager will send the exact price to your WhatsApp shortly."
],
"zh": [
"客户经理稍后会把准确报价发到你的 WhatsApp。"
],
"es": [
"Nuestro gerente te enviará el precio exacto a tu WhatsApp en breve."
]
},
"no_contact": {
"web": "Just tap the WhatsApp button at the top of this chat — our manager will reply within 12 hours!",
"app": "Drop your WhatsApp and our manager will reach out to you directly with the full quote!",
"already": "Got it — our manager will reach out to you at your WhatsApp shortly with the full quote!"
},
"zero_number": {
"long_number": "\\+?\\d[\\d\\s\\-().]{8,17}\\d",
"any_email": "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
},
"reask_patterns": [
{
"pattern": "(?:what|which)['′]?s\\s+(?:your|the)\\s+(?:whatsapp|number|phone|e-?mail|contact|号码|联系方式)",
"flags": "i"
},
{
"pattern": "(?:got|have)\\s+(?:your|the)\\s+(?:whatsapp|number|phone|e-?mail|contact)[^!?.]{0,60}\\?",
"flags": "i"
},
{
"pattern": "(?:i['′]ll\\s+|i\\s+)?(?:need|want)\\s+(?:your|the)\\s+(?:whatsapp|number|phone|e-?mail|contact|号码|联系方式)",
"flags": "i"
},
{
"pattern": "tell\\s+me\\s+(?:your\\s+)?(?:whatsapp|number|phone|e-?mail|contact|号码|联系方式)",
"flags": "i"
},
{
"pattern": "(?:could|can|would|may)\\s+you\\s+(?:leave|drop|share|give|provide|type|post)[^.!?\\n]{0,30}(?:whatsapp|number|phone|e-?mail|contact|号码|联系方式|微信|邮箱)",
"flags": "i"
},
{
"pattern": "(?:leave|drop|share|give)\\s+(?:me\\s+)?(?:your|us\\s+your?|a)\\s+(?:whatsapp|contact|number|e-?mail|联系方式)",
"flags": "i"
},
{
"pattern": "(?:drop|leave)\\s+yours\\b",
"flags": "i"
},
{
"pattern": "(?:whatsapp|e-?mail|contact)\\s+or\\s+(?:whatsapp|e-?mail|contact)\\s*\\?",
"flags": "i"
},
{
"pattern": "(?<!reach )(?<!reached )(?<!got )(?<!sent )(?<!did )(?<!to )your\\s+(?:whatsapp|number|phone|e-?mail|contact)\\b[^.!?]{0,20}[??]",
"flags": "i"
},
{
"pattern": "留[个下]?\\s*(?:你的?)?\\s*(?:whatsapp|微信|邮箱|联系方式|号码|电话)|给[我一]?个?\\s*(?:联系方式|whatsapp|微信|号码|邮箱|电话)|你的?\\s*(?:whatsapp|号码|电话|微信|邮箱|联系方式)[^。!?]{0,10}(?:是多少|多少|\\?)",
"flags": "i"
}
],
"triggers": {
"boundary": {
"pattern": "price|pricing|how\\s+much|\\bcost\\b|discount|cheaper|expensive|\\bfee\\b|quote|quotation|shipping\\s+(fee|cost|time)|freight|tariff|customs\\s+fee|best\\s+offer|any\\s+offer|free\\s+shipping|sample|certificat|\\bmoq\\b|minimum\\s+order|min\\s+order|container\\s+loading|fit\\s+in|per\\s+container|warranty|质保|保修|book(ing)?\\s|reserv|arrange|delivery|lead\\s+time|arriv|how\\s+long\\s+(does|will|would|to).*(take|arriv|deliver|ship)|roughly|ballpark|just\\s+tell|come\\s+on|at\\s+least\\s+(a|some|give)|budget|预算|价格|价钱|多少钱|报价|优惠|折扣|便宜|贵|划算|总价|落地|运费|关税|免费|到货|多久能到|交货|时效|发货|样品|证书|装柜|起订|预约|下单|定金|安排|大概|估个|估一|随便说|说个|求你|求了",
"flags": "i"
},
"budget": {
"pattern": "budget|预算",
"flags": "i"
},
"contact_ask": {
"pattern": "(your|our)\\s+(whatsapp|number|phone|email|contact)|(?<!i'll )(?<!i’ll )(?<!i will )(?<!let me )(contact|reach|call|email)\\s+(you|us)|你(们)?的?\\s?(whatsapp|号码|电话|微信|邮箱|联系方式)|(怎么|如何)联系|给我.{0,4}(号码|电话|联系方式)",
"flags": "i"
}
},
"reminders": {
"boundary": {
"budget": "⚠️ 职能边界提醒:客户报预算求推荐。推荐产品方案但绝不复述预算数字、不报价格 → 反问意向产品与需求规格 → 顺势引导留联系方式。",
"normal": "⚠️ 职能边界提醒:客户正在询问价格/优惠/交付时效/实质安排。绝对禁止给出任何价格数字(包括复述客户自己的预算)、交付时间或任何承诺,按职能边界对应话术处理。"
},
"contact_ask": {
"app_already": "⚠️ 客户正在索要我方联系方式,且客户已留过自己的联系方式。请逐字使用这句:\"Our manager will reach out to you at your WhatsApp shortly with the full quote!\"(中文同理)。绝对禁止输出任何号码或邮箱,也绝对禁止再索要客户已提供过的联系方式(缺失渠道可按轻补指引提一次;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认——仅系统提供的号码,禁止自编)。",
"app": "⚠️ 客户正在索要我方联系方式(最高意向信号)。当前为 App 会话,没有页面按钮——禁止使用任何 tap/button 按钮话术!请逐字使用这句:\"Drop your WhatsApp and our manager will reach out to you directly with the full quote!\"(中文同理引导客户留联系方式)。绝对禁止输出任何号码或邮箱。",
"web": "⚠️ 客户正在索要我方联系方式(最高意向信号)。请逐字使用这句指路:\"{no_contact_web}\"(邮箱同理指 Email 按钮)。绝对禁止口头报出任何号码或邮箱。"
},
"language_follow": {
"zh": "⚠️ 语言提醒:客户这条消息是中文——你的回复必须全程使用中文,一个英文单词都不能出现;模板句跟随客户语言自然表达(系统提醒提供的逐字话术优先用其语言版本,无则自然翻译保持意思与礼貌度);系统提供的补全号码逐字照抄,绝不改动数字。",
"es": "⚠️ 语言提醒:客户这条消息是西语——你的回复全程用西语,模板句跟随客户语言自然表达(系统提醒提供的逐字话术优先用其语言版本,无则自然翻译保持意思与礼貌度);系统提供的补全号码逐字照抄,绝不改动数字。"
},
"lead_given": {
"forbidden": "⚠️ 客户已提供联系方式({shown})。绝对禁止再索要客户已提供过的联系方式;缺失渠道仅可按轻补指引提一次;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认(仅系统提供的号码,禁止自编)。",
"respond_script": "需要回应时可直接逐字使用:\"{no_contact_already}\"(中文同理)。确认收到后继续解答客户问题即可,不必急着结束对话。",
"boundary_tail": "客户已留过联系方式——边界请求直接告知'客户经理会把准确报价/安排发到你 WhatsApp'即可,禁止再索要联系方式(缺失渠道可按轻补指引提一次;号码缺国家代码时按系统提醒回显补全后的完整号码请客户确认——仅系统提供的号码,禁止自编)。",
"suspect": "⚠️ 客户疑似已提供联系方式({shown})。禁止重新索要;可礼貌地请客户确认一次。"
},
"cc_guide": {
"echo": "⚠️ 号码确认指引(系统指令,绝对不要向客户提及这段说明):客户留下的号码不含国家代码,系统已按 IP 推测补全为 {intl}。请逐字使用这句:\"{cc_script}\" 本轮回复绝不写出任何号码数字——唯一例外是上面系统提供的补全号原文(逐字照抄,禁止自编或改动数字)。客户答复确认或纠正后,致谢即可,不再追问号码。",
"ask": "⚠️ 号码确认指引(系统指令,绝对不要向客户提及这段说明):客户留下的号码不含国家代码,且系统无法按 IP 推测补全。请逐字使用这句:\"{cc_script}\" 仅此一次,客户不给就不再提。客户答复后致谢即可,不再追问号码。"
},
"email_light": {
"en": "⚠️ 轻补指引(系统指令,绝对不要向客户提及这段说明):客户已留号码但还没留邮箱。请逐字使用这句:\"Got it! And an email address would help too — our manager will send the formal quotation PDF there.\" 仅此一次,客户不给就不再提。",
"zh": "⚠️ 轻补指引(系统指令,绝对不要向客户提及这段说明):客户已留号码但还没留邮箱。请逐字使用这句:\"收到!邮箱也留一个呗?客户经理把正式报价单 PDF 发你邮箱。\" 仅此一次,客户不给就不再提。"
}
},
"cc_templates": {
"ask": {
"en": "Could you send the full number with the country code, like +966 5x xxx xxxx? Just so our manager can reach you directly.",
"zh": "麻烦重发一下带国家代码的完整号码呗(比如 +966 5x xxx xxxx)?客户经理直接加你。",
"es": "¿Puedes enviar el número completo con el código de país, como +966 5x xxx xxxx? Así nuestro gerente puede contactarte directamente."
},
"wall": {
"en": "Got it — Could you send the full number with the country code, like +966 5x xxx xxxx? Just so our manager can reach you directly.",
"zh": "麻烦重发一下带国家代码的完整号码呗(比如 +966 5x xxx xxxx)?客户经理直接加你。",
"es": "Entendido — ¿Puedes enviar el número completo con el código de país, como +966 5x xxx xxxx? Así nuestro gerente puede contactarte directamente."
},
"note": {
"en": "⚠️ 轻补指引(系统指令,绝对不要向客户提及这段说明):客户留下的号码不含国家代码,客户经理无法直接回拨。请逐字使用这句:\"Could you send the full number with the country code, like +966 5x xxx xxxx? Just so our manager can reach you directly.\" 仅此一次,客户不给就不再提。",
"zh": "⚠️ 轻补指引(系统指令,绝对不要向客户提及这段说明):客户留下的号码不含国家代码,客户经理无法直接回拨。请逐字使用这句:\"麻烦重发一下带国家代码的完整号码呗(比如 +966 5x xxx xxxx)?客户经理直接加你。\" 仅此一次,客户不给就不再提。"
},
"echo": {
"en": "Got it — just to confirm: our manager will reach you at {intl} — is that right?",
"zh": "收到——跟您确认下:客户经理会通过 {intl} 联系您,这个号码对吗?",
"es": "Entendido — solo para confirmar: nuestro gerente te contactará al {intl} — ¿es correcto?"
}
}
}