refactor(backend): update service layers
- services/ontology.py: update ontology service logic - services/orchestrator.py: update orchestrator service logic - services/user_agent.py: update user agent service logic
This commit is contained in:
@@ -155,13 +155,20 @@ OPERATE_KEYWORDS = (
|
||||
|
||||
EXPENSE_TYPE_KEYWORDS = {
|
||||
"差旅": "travel",
|
||||
"出差": "travel",
|
||||
"住宿": "hotel",
|
||||
"酒店": "hotel",
|
||||
"交通": "transport",
|
||||
"打车": "transport",
|
||||
"网约车": "transport",
|
||||
"出租车": "transport",
|
||||
"停车费": "transport",
|
||||
"餐费": "meal",
|
||||
"用餐": "meal",
|
||||
"会务": "meeting",
|
||||
"招待费": "entertainment",
|
||||
"招待": "entertainment",
|
||||
"宴请": "entertainment",
|
||||
}
|
||||
|
||||
EXPENSE_NARRATIVE_KEYWORDS = (
|
||||
@@ -176,6 +183,10 @@ EXPENSE_NARRATIVE_KEYWORDS = (
|
||||
"打车",
|
||||
"车费",
|
||||
"餐费",
|
||||
"吃饭",
|
||||
"用餐",
|
||||
"宴请",
|
||||
"请客",
|
||||
"住宿",
|
||||
"发票",
|
||||
"票据",
|
||||
@@ -416,6 +427,11 @@ class SemanticOntologyService:
|
||||
permission=permission,
|
||||
missing_slots=missing_slots,
|
||||
ambiguity=ambiguity,
|
||||
allow_incomplete_draft=self._allow_incomplete_draft(
|
||||
context_json,
|
||||
scenario=scenario,
|
||||
intent=intent,
|
||||
),
|
||||
model_clarification_required=bool(
|
||||
model_parse is not None and model_parse.clarification_required
|
||||
),
|
||||
@@ -778,6 +794,8 @@ class SemanticOntologyService:
|
||||
"conversation_scenario": payload.context_json.get("conversation_scenario"),
|
||||
"conversation_intent": payload.context_json.get("conversation_intent"),
|
||||
"draft_claim_id": payload.context_json.get("draft_claim_id"),
|
||||
"review_action": payload.context_json.get("review_action"),
|
||||
"review_form_values": payload.context_json.get("review_form_values"),
|
||||
"conversation_history": payload.context_json.get("conversation_history", []),
|
||||
},
|
||||
"rule_candidates": {
|
||||
@@ -1004,6 +1022,10 @@ class SemanticOntologyService:
|
||||
suffix = match.group(1).strip()
|
||||
normalized = f"客户{suffix}".replace(" ", "")
|
||||
upsert(self._make_entity("customer", match.group(0).strip(), normalized, role="filter"))
|
||||
labeled_customer_match = re.search(r"客户名称[::]\s*(?P<name>[^\n,。;]+)", query)
|
||||
if labeled_customer_match:
|
||||
customer_name = labeled_customer_match.group("name").strip()
|
||||
upsert(self._make_entity("customer", customer_name, customer_name, role="filter"))
|
||||
|
||||
for match in re.finditer(r"供应商\s*([A-Za-z0-9一二三四五六七八九十]+)", query):
|
||||
suffix = match.group(1).strip()
|
||||
@@ -1062,6 +1084,35 @@ class SemanticOntologyService:
|
||||
if label in query:
|
||||
upsert(self._make_entity("expense_type", label, normalized, role="filter"))
|
||||
|
||||
has_customer_entertainment_signal = "客户" in query and any(
|
||||
keyword in query for keyword in ("吃饭", "用餐", "餐饮", "宴请", "请客", "招待")
|
||||
)
|
||||
if has_customer_entertainment_signal:
|
||||
upsert(
|
||||
self._make_entity(
|
||||
"expense_type",
|
||||
"客户招待",
|
||||
"entertainment",
|
||||
role="filter",
|
||||
confidence=0.96,
|
||||
)
|
||||
)
|
||||
|
||||
if any(keyword in query for keyword in ("打车", "网约车", "出租车", "车费", "停车费", "过路费")):
|
||||
upsert(self._make_entity("expense_type", "交通", "transport", role="filter", confidence=0.9))
|
||||
|
||||
if any(keyword in query for keyword in ("出差", "机票", "火车", "高铁", "行程单")):
|
||||
upsert(self._make_entity("expense_type", "差旅", "travel", role="filter", confidence=0.88))
|
||||
|
||||
if any(keyword in query for keyword in ("酒店", "住宿", "宾馆")):
|
||||
upsert(self._make_entity("expense_type", "住宿", "hotel", role="filter", confidence=0.86))
|
||||
|
||||
if (
|
||||
not has_customer_entertainment_signal
|
||||
and any(keyword in query for keyword in ("餐费", "用餐", "午餐", "晚餐", "早餐", "餐饮"))
|
||||
):
|
||||
upsert(self._make_entity("expense_type", "餐费", "meal", role="filter", confidence=0.84))
|
||||
|
||||
for amount in self._extract_amount_entities(query):
|
||||
upsert(amount)
|
||||
|
||||
@@ -1475,6 +1526,7 @@ class SemanticOntologyService:
|
||||
permission: OntologyPermission,
|
||||
missing_slots: list[str],
|
||||
ambiguity: list[str],
|
||||
allow_incomplete_draft: bool,
|
||||
model_clarification_required: bool,
|
||||
model_clarification_question: str | None,
|
||||
) -> tuple[bool, str | None]:
|
||||
@@ -1492,12 +1544,25 @@ class SemanticOntologyService:
|
||||
return True, "请说明这是报销、应收、应付,还是制度知识问题?"
|
||||
if intent == "compare" and len([item for item in entities if item.type != "amount"]) < 2:
|
||||
return True, "请补充需要对比的两个对象,例如两个客户、两个供应商或两个员工。"
|
||||
if allow_incomplete_draft and scenario == "expense" and intent == "draft":
|
||||
return False, None
|
||||
if missing_slots:
|
||||
return True, self._build_missing_slot_question(missing_slots)
|
||||
if ambiguity:
|
||||
return True, f"当前问题存在歧义,请进一步说明:{';'.join(ambiguity)}。"
|
||||
return False, None
|
||||
|
||||
@staticmethod
|
||||
def _allow_incomplete_draft(
|
||||
context_json: dict[str, Any],
|
||||
*,
|
||||
scenario: str,
|
||||
intent: str,
|
||||
) -> bool:
|
||||
if scenario != "expense" or intent != "draft":
|
||||
return False
|
||||
return str(context_json.get("review_action") or "").strip() == "save_draft"
|
||||
|
||||
@staticmethod
|
||||
def _display_slot_label(slot: str) -> str:
|
||||
return MISSING_SLOT_LABELS.get(slot, slot)
|
||||
|
||||
Reference in New Issue
Block a user