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

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
@@ -0,0 +1,91 @@
"""
海运协同群文字意图:DeepSeek A 判断补字段 / 产品报价 / 解散 / 其它。
本文件职责:只分类,不写主账、不发企微。
禁止:把「解散群」写成唯一口令;私聊按钮不走这里。
"""
from __future__ import annotations
import logging
from typing import Optional
from agent.llm.extract_text import extract_collab_fields
logger = logging.getLogger(__name__)
INTENT_FIELDS = "collab_fields"
INTENT_QUOTE = "product_quote"
INTENT_DISSOLVE = "dissolve"
INTENT_OTHER = "other"
_VALID = {INTENT_FIELDS, INTENT_QUOTE, INTENT_DISSOLVE, INTENT_OTHER}
def classify_group_text(
text: str,
*,
injected: str = "",
allow_network: Optional[bool] = None,
) -> str:
"""
群里一句文字的意图。单测可注入;正式走模型。
模型不可用时:只认带标签的协同字段(键:值是合同,不是口令),其余当其它。
"""
hint = (injected or "").strip()
if hint in _VALID:
return hint
raw = (text or "").strip()
if not raw:
return INTENT_OTHER
try:
from agent.config import get_settings
settings = get_settings()
use_net = (
allow_network
if allow_network is not None
else bool(getattr(settings, "llm_allow_network", False))
)
if use_net and getattr(settings, "llm_data_usage_confirmed", False):
got = _classify_with_model(raw, settings)
if got in _VALID:
return got
except Exception:
logger.exception("群意图模型失败,回退标签字段")
if extract_collab_fields(raw):
return INTENT_FIELDS
from agent.llm.extract_text import extract_product_quote
if extract_product_quote(raw):
return INTENT_QUOTE
return INTENT_OTHER
def _classify_with_model(text: str, settings) -> str:
"""DeepSeek 只回一个意图词。失败空串。"""
from agent.llm.http_client import LlmHttpClient
from agent.llm.modes import LlmMode
client = LlmHttpClient.from_settings(settings)
system = (
"你是海运协同群意图分类。只回复一个英文词,不要解释。"
"collab_fields=在补贸易条款/货好时间/商品海关编码/含油含电含磁;"
"product_quote=产品在报价格或费用;"
"dissolve=要把这个协同群解散;"
"other=闲聊、问候、对询价港口的随口更正(不当改单)。"
"一句话里既补字段又报价,回 product_quote。"
)
data = client.chat(
mode=LlmMode.ORDERED_ACTIONS,
messages=[
{"role": "system", "content": system},
{"role": "user", "content": text[:2000]},
],
)
content = str(getattr(data, "content", "") or "").strip().lower()
for token in (INTENT_QUOTE, INTENT_DISSOLVE, INTENT_FIELDS, INTENT_OTHER):
if token in content:
return token
return ""