私聊改口成普通货后不再被上一句违禁词拦住。
销售说运送衣服、改成衣服时,按新品名继续询价。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -82,6 +82,13 @@ _LABEL_EDIT = re.compile(
|
||||
r"(货物品名|品名|起运地|起运港|始发站|备注)\s*[::]\s*(\S+)"
|
||||
)
|
||||
_MULTI_SHEET = re.compile(r"段\s*\d|第\s*[一二三四五六七八九\d]\s*段")
|
||||
# 口语改口:运送衣服、改成衣服、换成衣服、炸弹换衣服。不认「换一下」「换个港口」。
|
||||
_SPOKEN_CARGO = re.compile(
|
||||
r"(?:运送|托运|发运|改成|改为|换成|换为)\s*([^\s,,。;;、请]{1,16})"
|
||||
r"|换(?!成|为|个|一下)([^\s,,。;;、请]{1,16})"
|
||||
)
|
||||
_CARGO_TAIL = re.compile(r"(请报价|报价|一下|吧|了)+$")
|
||||
_CARGO_SKIP = frozenset({"一下", "个", "报价", "价", "询价", "港口", "地方"})
|
||||
|
||||
# 销售侧说法写回内部键。起运地在主账里仍是起运港。
|
||||
_WRITE_KEYS = {
|
||||
@@ -132,6 +139,24 @@ def contains_blocked(text: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def spoken_cargo(text: str) -> str:
|
||||
"""
|
||||
从这一句里取出销售刚说的品名。
|
||||
|
||||
「运送衣服」「改成衣服」「换成衣服」「炸弹换衣服」都算。
|
||||
取最后一个说法,所以「炸弹换衣服」得到衣服。
|
||||
说出来的还是违禁词,或者只是「换一下」,就当没改口。
|
||||
"""
|
||||
found = ""
|
||||
for match in _SPOKEN_CARGO.finditer(text or ""):
|
||||
raw = match.group(1) or match.group(2) or ""
|
||||
value = _CARGO_TAIL.sub("", raw).strip(",,。;;、 ")
|
||||
if not value or value in _CARGO_SKIP or contains_blocked(value):
|
||||
continue
|
||||
found = value
|
||||
return found
|
||||
|
||||
|
||||
def apply_field_edits(text: str, facts: dict[str, Any]) -> dict[str, str]:
|
||||
"""
|
||||
把当前这句话里的「品名改为…」「起运地改为…」「备注改为…」写进字段。
|
||||
@@ -150,11 +175,18 @@ def apply_field_edits(text: str, facts: dict[str, Any]) -> dict[str, str]:
|
||||
for key in _WRITE_KEYS.get(label, (label,)):
|
||||
facts[key] = value
|
||||
written[key] = value
|
||||
cargo = spoken_cargo(text)
|
||||
if cargo:
|
||||
for key in ("品名", "货物品名"):
|
||||
facts[key] = cargo
|
||||
written[key] = cargo
|
||||
return written
|
||||
|
||||
|
||||
def is_cargo_rename(text: str) -> bool:
|
||||
"""当前句有没有把品名重新说成一个新值。没说品名的补重量不算改口。"""
|
||||
if spoken_cargo(text):
|
||||
return True
|
||||
body = text or ""
|
||||
labels = [label for label, _value in _FIELD_EDIT.findall(body)]
|
||||
if not _MULTI_SHEET.search(body):
|
||||
@@ -167,19 +199,23 @@ def judge(*, text: str, facts: dict[str, Any], hold: str) -> tuple[bool, str]:
|
||||
决定这一轮私聊能不能继续往建单走。
|
||||
|
||||
返回 (是否拦截, 新的未改口原话, 本句写下的字段)。
|
||||
当前句里仍有违禁词:拦住,并把这句记下来。
|
||||
当前句把品名说成普通货、且这句里没有违禁词:以前没落进字段的那句作废。
|
||||
当前句仍只是在说违禁词:拦住,并把这句记下来。
|
||||
当前句已经把品名说成普通货(运送衣服、改成衣服、换成衣服):前面的违禁原话作废。
|
||||
同一句里先提到旧词再改口,按改口后的品名放行。
|
||||
只补重量、件数:旧原话继续有效。
|
||||
品名改干净之后,起运地或备注里还留着违禁词,仍然拦截。
|
||||
会就地更新 facts 里本句写明的品名、起运地、备注。
|
||||
第三个返回值是本句写下的键,多段用来写回每一段,避免把别的字段盖掉。
|
||||
"""
|
||||
edits = apply_field_edits(text, facts)
|
||||
replaced = bool(spoken_cargo(text)) or is_cargo_rename(text)
|
||||
message_hit = contains_blocked(text)
|
||||
if message_hit:
|
||||
new_hold = (text or "").strip() or (hold or "")
|
||||
elif is_cargo_rename(text):
|
||||
if replaced and not contains_blocked(str(facts.get("品名") or "")):
|
||||
# 已经说出新的普通货品名。旧词留在这句里只是在改口,不再记住。
|
||||
new_hold = ""
|
||||
message_hit = False
|
||||
elif message_hit:
|
||||
new_hold = (text or "").strip() or (hold or "")
|
||||
else:
|
||||
new_hold = hold or ""
|
||||
field_text = "\n".join(str((facts or {}).get(key) or "") for key in _SCAN_KEYS)
|
||||
|
||||
@@ -157,6 +157,20 @@ class SeaPrivateFlowTests(unittest.TestCase):
|
||||
joined = "\n".join(self.replies)
|
||||
self.assertNotIn(BLOCK_REPLY, joined)
|
||||
|
||||
def test_oral_restatement_clears_previous_bomb(self) -> None:
|
||||
"""销售不说「品名改为」,直接重说运送衣服,或说改成衣服。"""
|
||||
hold = "10月30日,从广州去深圳,运送炸弹,请报价"
|
||||
facts = {"品名": "炸弹", "起运港": "广州"}
|
||||
for text in (
|
||||
"10月30日,从广州去深圳,运送衣服,请报价",
|
||||
"炸弹错了,给我改成衣服",
|
||||
"炸弹换衣服",
|
||||
):
|
||||
blocked, new_hold, edits = judge(text=text, facts=dict(facts), hold=hold)
|
||||
self.assertFalse(blocked, text)
|
||||
self.assertEqual(new_hold, "", text)
|
||||
self.assertEqual(edits.get("品名"), "衣服", text)
|
||||
|
||||
def test_weight_alone_does_not_clear(self) -> None:
|
||||
facts = dict(COMPLETE_SEA)
|
||||
facts["品名"] = "弹药"
|
||||
|
||||
Reference in New Issue
Block a user