落地海运协同群:测服靠会话存档听群话,报价单能带上协同字段。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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}],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user