feat: 海运协同不再补问贸易条款

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-20 17:52:19 +08:00
co-authored by Cursor
parent 698ac43878
commit 88a66d40bb
6 changed files with 32 additions and 13 deletions
+1 -1
View File
@@ -246,7 +246,7 @@ def extract_collab_fields(
""" """
群里协同字段:标签(冒号可省)+ 口语含油/含电/含磁/危险品、货好时间。 群里协同字段:标签(冒号可省)+ 口语含油/含电/含磁/危险品、货好时间。
allowed_keys 传入则只返回本单该有的项。不传则海运六项 ∪ 陆运协同键,给意图分类。 allowed_keys 传入则只返回本单该有的项。不传则海运协同五项 ∪ 贸易条款(陆运跨境仍要)∪ 陆运协同键,给意图分类。
闲聊、只说「纸箱」不进这里。商品海关编码 / HS 折成 HS编码。 闲聊、只说「纸箱」不进这里。商品海关编码 / HS 折成 HS编码。
""" """
from agent.schema.field_validate import ( from agent.schema.field_validate import (
+2 -2
View File
@@ -2091,12 +2091,12 @@ def group_fields_not_recognized(
keys: tuple[str, ...] | None = None, keys: tuple[str, ...] | None = None,
business_line: str = "", business_line: str = "",
) -> str: ) -> str:
"""没认出协同字段。陆运列出本单可补项;海运保持原六项口。""" """没认出协同字段。陆运列出本单可补项;海运列出协同五项(不含贸易条款)。"""
if keys: if keys:
line = (business_line or "").strip().upper() or "SEA" line = (business_line or "").strip().upper() or "SEA"
names = [collab_display_name(k, line) for k in keys] names = [collab_display_name(k, line) for k in keys]
return "听到了。请直接说" + "、".join(names) + "。" return "听到了。请直接说" + "、".join(names) + "。"
return "听到了。请直接说贸易条款、货好时间、商品海关编码、是否含油/含电/含磁。" return "听到了。请直接说货好时间、商品海关编码、是否含油/含电/含磁。"
def group_deal_stale(*, work_order_no: str) -> str: def group_deal_stale(*, work_order_no: str) -> str:
+1 -1
View File
@@ -2,7 +2,7 @@
海运协同群业务:填表进群、补字段重发、产品报价、附件、解散、成交跟进。 海运协同群业务:填表进群、补字段重发、产品报价、附件、解散、成交跟进。
本文件职责:群里副作用(主账+企微群)。私聊按钮仍走 sea_text_flow.on_button。 本文件职责:群里副作用(主账+企微群)。私聊按钮仍走 sea_text_flow.on_button。
禁止:改询价七项;终态默默忽略;把销售附件当报价。 禁止:改询价十项;终态默默忽略;把销售附件当报价。
""" """
from __future__ import annotations from __future__ import annotations
+1 -1
View File
@@ -231,7 +231,7 @@ def _classify_with_model(text: str, settings) -> str:
client = LlmHttpClient.from_settings(settings) client = LlmHttpClient.from_settings(settings)
system = ( system = (
"你是海运协同群意图分类。只回复一个英文词,不要解释。" "你是海运协同群意图分类。只回复一个英文词,不要解释。"
"collab_fields=在补贸易条款/货好时间/商品海关编码/含油含电含磁;" "collab_fields=在补货好时间/商品海关编码/含油含电含磁;"
"quote_adjust=销售在调已有费用,口令不写死(上升、上浮、往上抬、加一成、减、改到某金额都算),不是新产品报价;" "quote_adjust=销售在调已有费用,口令不写死(上升、上浮、往上抬、加一成、减、改到某金额都算),不是新产品报价;"
"product_quote=产品在报价格或费用(含具体金额);" "product_quote=产品在报价格或费用(含具体金额);"
"quote_confirm_tms=产品确认沿用当前TMS报价,没有报新金额;" "quote_confirm_tms=产品确认沿用当前TMS报价,没有报新金额;"
+4 -4
View File
@@ -60,7 +60,7 @@ LAND_DISPLAY = {
# 协同补充字段:拉群后可静默写入,不挡首次查价。内部键仍是 HS编码。 # 协同补充字段:拉群后可静默写入,不挡首次查价。内部键仍是 HS编码。
SEA_COLLAB_FIELDS = ("货好时间", "HS编码", "是否含油", "是否含电", "是否含磁") SEA_COLLAB_FIELDS = ("货好时间", "HS编码", "是否含油", "是否含电", "是否含磁")
# 空运群只补含电/含磁,摘要不要把海运六项搬过去。 # 空运群只补含电/含磁,摘要不要把海运协同五项搬过去。
AIR_COLLAB_FIELDS = ("是否含电", "是否含磁") AIR_COLLAB_FIELDS = ("是否含电", "是否含磁")
# 群摘要对外展示名。内部继续用 HS编码,避免改合同键。 # 群摘要对外展示名。内部继续用 HS编码,避免改合同键。
SEA_COLLAB_DISPLAY = { SEA_COLLAB_DISPLAY = {
@@ -143,11 +143,11 @@ _LAND_COLLAB_BY_PAIR: dict[tuple[str, str], tuple[str, ...]] = {
"是否为危险品", "是否为危险品",
), ),
} }
# 意图分类用:海运六项 ∪ 陆运全部协同键。 # 意图分类用:海运协同五项 ∪ 贸易条款(陆运跨境仍要)∪ 陆运协同键。
ALL_COLLAB_KEYS = tuple( ALL_COLLAB_KEYS = tuple(
dict.fromkeys( dict.fromkeys(
list(SEA_COLLAB_FIELDS) list(SEA_COLLAB_FIELDS)
+ ["客户名称", "包装方式", "货值", "是否为危险品", "车型/数量"] + ["贸易条款", "客户名称", "包装方式", "货值", "是否为危险品", "车型/数量"]
) )
) )
@@ -319,7 +319,7 @@ def land_collab_fields(land_type: str, route: str) -> tuple[str, ...]:
""" """
本单陆运协同内部键,顺序与规格一致。 本单陆运协同内部键,顺序与规格一致。
对不上填写样例返回空元组,调用方不得按海运六项去列。 对不上填写样例返回空元组,调用方不得按海运协同五项去列。
海关编码内部仍是 HS编码。副作用:无。 海关编码内部仍是 HS编码。副作用:无。
""" """
from agent.schema.land_options import canonicalize_route, canonicalize_transport_type from agent.schema.land_options import canonicalize_route, canonicalize_transport_type
+23 -4
View File
@@ -631,6 +631,9 @@ class SeaSkipAndPullTests(unittest.TestCase):
self.assertIn(wo, group_text) self.assertIn(wo, group_text)
self.assertIn("起运港", group_text) self.assertIn("起运港", group_text)
self.assertIn("贸易条款", group_text) self.assertIn("贸易条款", group_text)
collab_block = group_text.split("协同补充字段:", 1)[-1].split("TMS报价:", 1)[0]
self.assertNotIn("贸易条款", collab_block)
self.assertIn("货好时间", collab_block)
self.assertIn("商品海关编码", group_text) self.assertIn("商品海关编码", group_text)
self.assertNotIn("HS编码", group_text) self.assertNotIn("HS编码", group_text)
self.assertIn("TMS", group_text) self.assertIn("TMS", group_text)
@@ -842,7 +845,7 @@ class SeaGroupCollabFieldTests(unittest.TestCase):
def _reply(self, text: str, extra=None) -> None: def _reply(self, text: str, extra=None) -> None:
self.replies.append(text) self.replies.append(text)
def test_group_text_writes_incoterm_silently(self) -> None: def test_group_text_ignores_trade_terms_saves_ready_date(self) -> None:
self.ledger.set_sea_staff( self.ledger.set_sea_staff(
[ [
{ {
@@ -870,11 +873,24 @@ class SeaGroupCollabFieldTests(unittest.TestCase):
ticket = self.ledger.get_ticket(work_order_no=wo) ticket = self.ledger.get_ticket(work_order_no=wo)
chat_id = ticket.collab_chat_id chat_id = ticket.collab_chat_id
n = len(self.replies) n = len(self.replies)
phase = handle_group_collab( ignored = handle_group_collab(
InboundMessage( InboundMessage(
sender_id="prod4", sender_id="prod4",
message_id="g1", message_id="g1",
content="贸易条款:FOB", content="贸易条款:CIF",
chat_id=chat_id,
chat_type="group",
),
flow=self.flow,
ledger=self.ledger,
)
self.assertEqual(ignored, "collab_not_recognized")
self.assertFalse(ticket.collab_facts.get("贸易条款"))
phase = handle_group_collab(
InboundMessage(
sender_id="prod4",
message_id="g2",
content="货好时间:下周",
chat_id=chat_id, chat_id=chat_id,
chat_type="group", chat_type="group",
), ),
@@ -883,7 +899,7 @@ class SeaGroupCollabFieldTests(unittest.TestCase):
) )
self.assertEqual(phase, "collab_field_saved") self.assertEqual(phase, "collab_field_saved")
self.assertEqual(len(self.replies), n) self.assertEqual(len(self.replies), n)
self.assertEqual(ticket.collab_facts.get("贸易条款"), "FOB") self.assertEqual(ticket.collab_facts.get("货好时间"), "下周")
def test_group_price_chat_is_ignored(self) -> None: def test_group_price_chat_is_ignored(self) -> None:
self.ledger.set_sea_staff( self.ledger.set_sea_staff(
@@ -1241,6 +1257,9 @@ class SeaGroupCopyTests(unittest.TestCase):
self.assertIn("询价字段:\n运输方式:海运", text) self.assertIn("询价字段:\n运输方式:海运", text)
self.assertIn("\n\n协同补充字段:\n", text) self.assertIn("\n\n协同补充字段:\n", text)
self.assertIn("商品海关编码:-", text) self.assertIn("商品海关编码:-", text)
self.assertIn("货好时间:-", text)
collab_block = text.split("协同补充字段:", 1)[-1].split("TMS报价:", 1)[0]
self.assertNotIn("贸易条款", collab_block)
self.assertNotIn("HS编码", text) self.assertNotIn("HS编码", text)
self.assertIn("\n\nTMS报价:\nTMS 暂无匹配报价", text) self.assertIn("\n\nTMS报价:\nTMS 暂无匹配报价", text)
self.assertNotIn("未查到合适报价", text) self.assertNotIn("未查到合适报价", text)