99f51e7703
审查(With fixes)四项:
- Important-1: LONG_NUMBER_RE {9,17}→{8,17}——旧量词最小匹配 11 字符,
纯 10 位号(沙特裸号 0501234567,CC 模板范例市场本体)穿透。实测钉死
行为边界: 逗号不在字符类,"50,000,000" 千分位形态仍放行(与
"45,000 km" 同机制,审查预估会命中系漏算逗号);空格分隔 ≥10 位命中;
DN110/5000m/VIN 规格形态全放行
- Important-2: CC 触发轮回显被零号码墙拦下时(violation==no_contact),
closing 改用 CC 模板句而非 NO_CONTACT_ALREADY——GLM 有 3/3 回显倾向,
客户该收到追问而非"稍后联系"虚假承诺;价格墙路径不变。设计文档 §2
补记该裁决
- Minor-4: breach_rate.py 补号码回显(≥10位,与墙同形)与邮箱回显两条
观测模式,补上漏放观测盲区
- Minor-5: violated 收尾与已流出前缀之间补空格分隔("...xxxx? Got it —"),
空格随 closing 一起流出,客户所见与落库一致;CC/触发轮缓冲未流出,
emitted 恒空天然不受影响
测试 256 passed(253+3)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
54 lines
2.3 KiB
Python
54 lines
2.3 KiB
Python
"""职能边界破防率观测(只读): AI 回复中出现"价格形态数字"的轮次占比。
|
||
方案B(输出过滤)的启动依据: >10% 即砌墙。锚定式匹配,年份/规格数字天然不命中。"""
|
||
import re
|
||
import sqlite3
|
||
import sys
|
||
|
||
DB = sys.argv[1] if len(sys.argv) > 1 else "./data/hesupipe_ai_kefu.db"
|
||
|
||
PATTERNS = [
|
||
(r"\$\s?\d", "美元符"),
|
||
(r"[€£]\s?\d", "欧元/英镑符"),
|
||
(r"\d[\d,.]*\s*(usd|美元|万块?|块钱)", "货币单位"),
|
||
(r"\d[\d,.]*\s*(d[óo]lares?|euros?\b(?!\s*pallets?)|рублей|руб\.?|"
|
||
r"доллар(?:ов|а|ы)?)", "货币单位(多语言)"),
|
||
(r"\b(?:precio?s?|costo?s?|custo?s?|preço?s?|цен[аы]?|стоимость|"
|
||
r"(?:ال)?سعر|(?:ال)?أسعار|(?:ال)?ثمن)\b"
|
||
r"[^\d\n]{0,20}(?<![a-z])\d", "价格名词前置(多语言)"),
|
||
(r"(price|cost|quote)[^.\d]{0,20}(?<![a-z])(?!(?:19|20)\d\d(?!\d))\d",
|
||
"价格动词邻接(年份排除)"),
|
||
(r"\d[\d,.]*\s*k\b(?!\w)", "25k形式"),
|
||
(r"\d+\s*[- ]?(day|week|month|d[ií]as?|semanas?|дн(?:ей|я)|недел[ьи]|"
|
||
r"أيام)s?\b", "交期/时间承诺"),
|
||
# Minor-4(审查修复): 号码回显漏放观测——与零号码墙 LONG_NUMBER_RE 同形
|
||
# ({8,17} 修复后口径),AI 回复中 ≥10 位数字串(含分隔/阿语数字形态)
|
||
(r"\+?\d[\d\s\-().]{8,17}\d", "号码回显(≥10位)"),
|
||
(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", "邮箱回显"),
|
||
]
|
||
COMPILED = [(re.compile(p, re.I), name) for p, name in PATTERNS]
|
||
|
||
|
||
def main() -> None:
|
||
conn = sqlite3.connect(f"file:{DB}?mode=ro", uri=True)
|
||
rows = conn.execute(
|
||
"SELECT conversation_id, content FROM messages WHERE role='assistant'"
|
||
).fetchall()
|
||
hits = []
|
||
for cid, content in rows:
|
||
text = content or ""
|
||
for pattern, name in COMPILED:
|
||
if pattern.search(text):
|
||
hits.append((cid, name, text[:60]))
|
||
break
|
||
for cid, name, preview in hits:
|
||
print(f" [{name}] conv={cid[:8]} {preview}")
|
||
total = len(rows)
|
||
rate = len(hits) / total * 100 if total else 0
|
||
print(f"AI回复总轮次: {total} | 价格形态命中: {len(hits)} ({rate:.0f}%)")
|
||
print("← 破防率。>10% 启动方案B(输出过滤)")
|
||
conn.close()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|