角色业务范围收紧工单与模板;报价日期不当费用;未选舱不迁已报价;另开一票可清违禁 hold

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-10-15 21:00:01 +08:00
co-authored by Cursor
parent a0c705683f
commit 277cdc1c28
39 changed files with 2083 additions and 217 deletions
@@ -7,7 +7,10 @@
from __future__ import annotations
import json
import logging
import time
from pathlib import Path
from typing import Optional
from agent.policy import inquiry_copy as copy
@@ -32,6 +35,7 @@ from agent.routing.group_intent import (
logger = logging.getLogger(__name__)
INTENT_ACTIVATE = "air_activate"
INTENT_LOCK = "air_lock"
INTENT_RELEASE = "air_release"
@@ -131,18 +135,50 @@ def classify_air_group_text(
if use_net and getattr(settings, "llm_data_usage_confirmed", False):
got = _classify_with_model(raw, settings)
if got in _VALID:
return _prefer_staff_quote(got, raw)
preferred = _prefer_staff_quote(got, raw)
from agent.llm.extract_text import (
extract_product_quote,
is_non_fee_meta_only_message,
is_quote_date_only_message,
labeled_quote_date,
)
# 模型若把「报价日期/有效期/时效」判成报价:有日期/含电含磁回补字段,否则 other。
if preferred == INTENT_QUOTE and (
is_quote_date_only_message(raw)
or is_non_fee_meta_only_message(raw)
or (labeled_quote_date(raw) and not extract_product_quote(raw))
):
if labeled_quote_date(raw) or (
"是否含电" in raw or "是否含磁" in raw or "是否带电" in raw
):
preferred = INTENT_FIELDS
elif is_non_fee_meta_only_message(raw):
preferred = INTENT_OTHER
else:
preferred = INTENT_FIELDS
return preferred
except Exception:
logger.exception("空运群意图模型失败,回退规则")
from agent.llm.extract_text import extract_air_collab_fields, extract_product_quote
from agent.llm.extract_text import (
extract_air_collab_fields,
extract_product_quote,
is_non_fee_meta_only_message,
is_quote_date_only_message,
labeled_quote_date,
)
from agent.schema.quote_adjust import extract_adjust
# 费用金额先当航线报价。「空运费改为900」不是销售调价。
# 报价有效期/时效要求整句不是报价。
if is_non_fee_meta_only_message(raw) and not labeled_quote_date(raw):
return INTENT_OTHER
if text_is_staff_fee_quote(raw):
return INTENT_QUOTE
if extract_adjust(raw).is_adjust:
return INTENT_ADJUST
if extract_product_quote(raw):
quote_hit = extract_product_quote(raw)
if quote_hit:
return INTENT_QUOTE
confirmed = _hint_confirm_tms(raw)
if confirmed:
@@ -153,7 +189,9 @@ def classify_air_group_text(
closed = _hint_deal_outcome(raw)
if closed:
return closed
if extract_air_collab_fields(raw):
air_fields = extract_air_collab_fields(raw)
quote_date = labeled_quote_date(raw)
if air_fields or quote_date:
return INTENT_FIELDS
if _looks_like_option(raw):
return INTENT_PICK_OPTION
@@ -244,7 +282,8 @@ def _classify_with_model(text: str, settings) -> str:
"说出释放舱位、释放舱、把舱位释放了时不要回 air_release;"
"air_activate=只是指定/切换工单号;"
"air_pick_option=在补充或选择舱位编号、航司、航班号,写法不限;"
"collab_fields=在补是否含电/是否含磁;"
"collab_fields=在补是否含电/是否含磁/是否带电,或补报价日期;"
"只有报价有效期或时效要求、没有费用金额时回 other,不要回 product_quote;"
"quote_adjust=销售在按比例改已有费用(上调、上浮、加10%、减5%、加一成),或只改总价/总销售价;"
"product_quote=航线在报某一项费用的金额。写出「空运费9900」「空运费改为900USD」是报价,不是调价;"
"quote_confirm_tms=确认沿用当前TMS报价;"
@@ -264,5 +303,7 @@ def _classify_with_model(text: str, settings) -> str:
{"role": "user", "content": text[:500]},
],
)
got = str((data or {}).get("content") or "").strip().split()[0] if data else ""
# chat 返回 LlmHttpResult,不是 dict。
content = str(getattr(data, "content", "") or "").strip()
got = content.split()[0] if content else ""
return got if got in _VALID else ""