落地海运协同群:测服靠会话存档听群话,报价单能带上协同字段。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-15 18:12:45 +08:00
co-authored by Cursor
parent 235ecd8c83
commit 12219cacb1
39 changed files with 4436 additions and 256 deletions
+65 -7
View File
@@ -23,12 +23,12 @@ _MODE_WORDS = (
_LABEL_LINE = re.compile(
r"^(起运地|起运港|目的地|目的港|品名|件数|毛重|体积|重量|重量\(KG\)|体积\(CBM\)|"
r"包装方式|包装类型|货量|货物数量|整柜或拼柜|箱型箱量|报价日期|车型数量|"
r"贸易条款|货好时间|HS编码|HS|是否含油|是否含电|是否含磁)\s*[::]\s*(.+)$"
r"贸易条款|货好时间|商品海关编码|海关编码|HS编码|HS|是否含油|是否含电|是否含磁)\s*[::]\s*(.+)$"
)
_LABEL_INLINE = re.compile(
r"(起运地|起运港|目的地|目的港|品名|件数|毛重|体积|重量|重量\(KG\)|体积\(CBM\)|"
r"包装方式|包装类型|货量|货物数量|整柜或拼柜|箱型箱量|报价日期|车型数量|"
r"贸易条款|货好时间|HS编码|HS|是否含油|是否含电|是否含磁)\s*[::]\s*(\S+)"
r"贸易条款|货好时间|商品海关编码|海关编码|HS编码|HS|是否含油|是否含电|是否含磁)\s*[::]\s*(\S+)"
)
@@ -118,18 +118,76 @@ def extract_inquiry_snapshot(
}
def extract_collab_fields(text: str) -> dict[str, str]:
def extract_collab_fields(
text: str,
*,
allow_b: bool = False,
injected: Optional[dict[str, str]] = None,
) -> dict[str, str]:
"""
群里协同字段:只收带标签的非空值。
群里协同字段:标签「键:值」+ 口语含油/含电/含磁、货好时间。
闲聊、报价金额、附件本轮不进这里。HS 折成 HS编码。
闲聊、报价金额不进这里。商品海关编码 / HS 折成 HS编码。
allow_b 保留给调用方;协同六项不走询价七项的 B 合同。
"""
from agent.schema.field_validate import SEA_COLLAB_FIELDS, normalize_facts
from agent.schema.field_validate import (
SEA_COLLAB_FIELDS,
harvest_oral_collab,
normalize_facts,
)
del allow_b
if injected:
return {
k: str(v).strip()
for k, v in normalize_facts(dict(injected)).items()
if k in SEA_COLLAB_FIELDS and str(v or "").strip()
}
labeled = normalize_facts(parse_labeled_facts(text))
oral = harvest_oral_collab(text)
merged = dict(oral)
merged.update({k: v for k, v in labeled.items() if v})
out: dict[str, str] = {}
for key in SEA_COLLAB_FIELDS:
val = (labeled.get(key) or "").strip()
val = (merged.get(key) or "").strip()
if val:
out[key] = val
return out
_RE_MONEY = re.compile(
r"(?:USD|CNY|RMB|美金|美元|人民币)?\s*(\d+(?:\.\d+)?)\s*(?:USD|CNY|RMB|美金|美元|人民币|元)?"
r"|(?:USD|CNY|RMB|美金|美元)\s*(\d+(?:\.\d+)?)",
re.I,
)
def extract_product_quote(text: str, *, injected: Optional[dict[str, Any]] = None) -> dict[str, Any]:
"""
产品文字报价:抽出合计/币别。注入优先。
认不出价格返回空 dict,调用方回「没有识别到报价」。
"""
if isinstance(injected, dict) and (injected.get("total") or injected.get("fee_rows")):
out = dict(injected)
out.setdefault("source_label", "产品报价")
return out
raw = (text or "").strip()
if not raw:
return {}
hit = _RE_MONEY.search(raw)
if not hit:
return {}
amount = (hit.group(1) or hit.group(2) or "").strip()
if not amount:
return {}
ccy = "USD"
if any(x in raw.upper() for x in ("CNY", "RMB", "人民币", "元")):
ccy = "CNY"
return {
"total": amount,
"currency": ccy,
"source_label": "产品报价",
"raw_text": raw,
"fee_rows": [{"name": "海运费", "amount": amount, "currency": ccy}],
}