feat(server): 新增运行时聊天服务和用户代理服务,支持智能对话和用户行为分析

This commit is contained in:
caoxiaozhu
2026-05-14 09:32:49 +00:00
parent b0fef46fc6
commit bac3f00ae4
2 changed files with 73 additions and 7 deletions

View File

@@ -27,7 +27,7 @@ class RuntimeChatService:
def complete( def complete(
self, self,
messages: list[dict[str, str]], messages: list[dict[str, Any]],
*, *,
slot_priority: tuple[str, ...] = ("main", "backup"), slot_priority: tuple[str, ...] = ("main", "backup"),
max_tokens: int = 500, max_tokens: int = 500,
@@ -91,7 +91,7 @@ class RuntimeChatService:
def _request_chat_completion( def _request_chat_completion(
self, self,
config: dict[str, str], config: dict[str, str],
messages: list[dict[str, str]], messages: list[dict[str, Any]],
*, *,
max_tokens: int, max_tokens: int,
temperature: float, temperature: float,
@@ -136,7 +136,7 @@ class RuntimeChatService:
endpoint: str, endpoint: str,
model: str, model: str,
api_key: str, api_key: str,
messages: list[dict[str, str]], messages: list[dict[str, Any]],
max_tokens: int, max_tokens: int,
temperature: float, temperature: float,
) -> str: ) -> str:
@@ -165,7 +165,7 @@ class RuntimeChatService:
endpoint: str, endpoint: str,
model: str, model: str,
api_key: str, api_key: str,
messages: list[dict[str, str]], messages: list[dict[str, Any]],
max_tokens: int, max_tokens: int,
temperature: float, temperature: float,
) -> str: ) -> str:
@@ -197,7 +197,7 @@ class RuntimeChatService:
endpoint: str, endpoint: str,
model: str, model: str,
api_key: str, api_key: str,
messages: list[dict[str, str]], messages: list[dict[str, Any]],
max_tokens: int, max_tokens: int,
temperature: float, temperature: float,
) -> str: ) -> str:

View File

@@ -2124,6 +2124,61 @@ class UserAgentService:
item: dict[str, object], item: dict[str, object],
payload: UserAgentRequest, payload: UserAgentRequest,
) -> dict[str, str]: ) -> dict[str, str]:
provided_type = str(item.get("document_type") or "").strip().lower()
expense_type_code = self._collect_entity_values(payload).get("expense_type_code", "")
has_customer = bool(self._collect_entity_values(payload).get("customer"))
if provided_type:
if provided_type in {"flight_itinerary", "train_ticket"}:
return {
"document_type": provided_type,
"expense_type": "travel",
"group_code": "travel",
"scene_label": "差旅票据",
}
if provided_type == "hotel_invoice":
return {
"document_type": provided_type,
"expense_type": "hotel",
"group_code": "travel",
"scene_label": "住宿票据",
}
if provided_type in {"taxi_receipt", "parking_toll_receipt"}:
return {
"document_type": provided_type,
"expense_type": "transport",
"group_code": "travel",
"scene_label": "交通票据",
}
if provided_type == "meal_receipt":
group_code = "entertainment" if expense_type_code == "entertainment" or has_customer else "meal"
return {
"document_type": provided_type,
"expense_type": group_code,
"group_code": group_code,
"scene_label": "餐饮票据",
}
if provided_type == "office_invoice":
return {
"document_type": provided_type,
"expense_type": "office",
"group_code": "office",
"scene_label": "办公用品票据",
}
if provided_type == "meeting_invoice":
return {
"document_type": provided_type,
"expense_type": "meeting",
"group_code": "meeting",
"scene_label": "会务票据",
}
if provided_type == "training_invoice":
return {
"document_type": provided_type,
"expense_type": "training",
"group_code": "training",
"scene_label": "培训票据",
}
text = " ".join( text = " ".join(
[ [
str(item.get("filename") or ""), str(item.get("filename") or ""),
@@ -2132,8 +2187,6 @@ class UserAgentService:
] ]
).lower() ).lower()
compact = text.replace(" ", "") compact = text.replace(" ", "")
expense_type_code = self._collect_entity_values(payload).get("expense_type_code", "")
has_customer = bool(self._collect_entity_values(payload).get("customer"))
if any(keyword in compact for keyword in ("机票", "航班", "火车", "高铁", "行程单")): if any(keyword in compact for keyword in ("机票", "航班", "火车", "高铁", "行程单")):
return { return {
@@ -2187,6 +2240,19 @@ class UserAgentService:
return "other" return "other"
def _extract_document_fields(self, item: dict[str, object]) -> dict[str, str]: def _extract_document_fields(self, item: dict[str, object]) -> dict[str, str]:
raw_fields = item.get("document_fields")
if isinstance(raw_fields, list):
normalized_fields: dict[str, str] = {}
for field in raw_fields:
if not isinstance(field, dict):
continue
label = str(field.get("label") or "").strip()
value = str(field.get("value") or "").strip()
if label and value:
normalized_fields[label] = value
if normalized_fields:
return normalized_fields
text = " ".join([str(item.get("summary") or ""), str(item.get("text") or "")]).strip() text = " ".join([str(item.get("summary") or ""), str(item.get("text") or "")]).strip()
fields: dict[str, str] = {} fields: dict[str, str] = {}
amount_match = AMOUNT_TEXT_PATTERN.search(text) amount_match = AMOUNT_TEXT_PATTERN.search(text)