feat: 增强 Agent 系统和完善项目结构
主要改进: - Agent 增强: 订单查询、售后支持、客服路由等功能优化 - 新增语言检测和 Token 管理模块 - 改进 Chatwoot webhook 处理和用户标识 - MCP 服务器增强: 订单 MCP 和 Strapi MCP 功能扩展 - 新增商城客户端、知识库、缓存和同步模块 - 添加多语言提示词系统 (YAML) - 完善项目结构: 整理文档、脚本和测试文件 - 新增调试和测试工具脚本 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,92 +4,24 @@ Router Agent - Intent recognition and routing
|
||||
import json
|
||||
from typing import Any, Optional
|
||||
|
||||
from core.state import AgentState, Intent, ConversationState, set_intent, add_entity
|
||||
from core.state import AgentState, Intent, ConversationState, set_intent, add_entity, set_language
|
||||
from core.llm import get_llm_client, Message
|
||||
from core.language_detector import get_cached_or_detect
|
||||
from prompts import get_prompt
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
# Intent classification prompt
|
||||
CLASSIFICATION_PROMPT = """你是一个 B2B 购物网站的智能助手路由器。
|
||||
你的任务是分析用户消息,识别用户意图并提取关键实体。
|
||||
|
||||
## 可用意图分类
|
||||
|
||||
1. **customer_service** - 通用咨询
|
||||
- FAQ 问答
|
||||
- 产品使用问题
|
||||
- 公司信息查询
|
||||
- 政策咨询(退换货政策、隐私政策等)
|
||||
|
||||
2. **order** - 订单相关
|
||||
- 订单查询("我的订单在哪"、"查一下订单")
|
||||
- 物流跟踪("快递到哪了"、"什么时候到货")
|
||||
- 订单修改("改一下收货地址"、"修改订单数量")
|
||||
- 订单取消("取消订单"、"不想要了")
|
||||
- 发票查询("开发票"、"要发票")
|
||||
|
||||
3. **aftersale** - 售后服务
|
||||
- 退货申请("退货"、"不满意想退")
|
||||
- 换货申请("换货"、"换一个")
|
||||
- 投诉("投诉"、"服务态度差")
|
||||
- 工单/问题反馈
|
||||
|
||||
4. **product** - 商品相关
|
||||
- 商品搜索("有没有xx"、"找一下xx")
|
||||
- 商品推荐("推荐"、"有什么好的")
|
||||
- 询价("多少钱"、"批发价"、"大量购买价格")
|
||||
- 库存查询("有货吗"、"还有多少")
|
||||
|
||||
5. **human_handoff** - 需要转人工
|
||||
- 用户明确要求转人工
|
||||
- 复杂问题 AI 无法处理
|
||||
- 敏感问题需要人工处理
|
||||
|
||||
## 实体提取
|
||||
|
||||
请从消息中提取以下实体(如果存在):
|
||||
- order_id: 订单号(如 ORD123456)
|
||||
- product_id: 商品ID
|
||||
- product_name: 商品名称
|
||||
- quantity: 数量
|
||||
- date_reference: 时间引用(今天、昨天、上周、具体日期等)
|
||||
- tracking_number: 物流单号
|
||||
- phone: 电话号码
|
||||
- address: 地址信息
|
||||
|
||||
## 输出格式
|
||||
|
||||
请以 JSON 格式返回,包含以下字段:
|
||||
```json
|
||||
{
|
||||
"intent": "意图分类",
|
||||
"confidence": 0.95,
|
||||
"sub_intent": "子意图(可选)",
|
||||
"entities": {
|
||||
"entity_type": "entity_value"
|
||||
},
|
||||
"reasoning": "简短的推理说明"
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
- 如果意图不明确,置信度应该较低
|
||||
- 如果无法确定意图,返回 "unknown"
|
||||
- 实体提取要准确,没有的字段不要填写
|
||||
"""
|
||||
|
||||
|
||||
async def classify_intent(state: AgentState) -> AgentState:
|
||||
"""Classify user intent and extract entities
|
||||
|
||||
|
||||
This is the first node in the workflow that analyzes the user's message
|
||||
and determines which agent should handle it.
|
||||
|
||||
|
||||
Args:
|
||||
state: Current agent state
|
||||
|
||||
|
||||
Returns:
|
||||
Updated state with intent and entities
|
||||
"""
|
||||
@@ -98,24 +30,38 @@ async def classify_intent(state: AgentState) -> AgentState:
|
||||
conversation_id=state["conversation_id"],
|
||||
message=state["current_message"][:100]
|
||||
)
|
||||
|
||||
|
||||
state["state"] = ConversationState.CLASSIFYING.value
|
||||
state["step_count"] += 1
|
||||
|
||||
|
||||
# Detect language
|
||||
detected_locale = get_cached_or_detect(state, state["current_message"])
|
||||
confidence = 0.85 # Default confidence for language detection
|
||||
state = set_language(state, detected_locale, confidence)
|
||||
|
||||
logger.info(
|
||||
"Language detected",
|
||||
locale=detected_locale,
|
||||
confidence=confidence
|
||||
)
|
||||
|
||||
# Build context from conversation history
|
||||
context_summary = ""
|
||||
if state["context"]:
|
||||
context_parts = []
|
||||
if state["context"].get("order_id"):
|
||||
context_parts.append(f"当前讨论的订单: {state['context']['order_id']}")
|
||||
context_parts.append(f"Current order: {state['context']['order_id']}")
|
||||
if state["context"].get("product_id"):
|
||||
context_parts.append(f"当前讨论的商品: {state['context']['product_id']}")
|
||||
context_parts.append(f"Current product: {state['context']['product_id']}")
|
||||
if context_parts:
|
||||
context_summary = "\n".join(context_parts)
|
||||
|
||||
|
||||
# Load prompt in detected language
|
||||
classification_prompt = get_prompt("router", detected_locale)
|
||||
|
||||
# Build messages for LLM
|
||||
messages = [
|
||||
Message(role="system", content=CLASSIFICATION_PROMPT),
|
||||
Message(role="system", content=classification_prompt),
|
||||
]
|
||||
|
||||
# Add recent conversation history for context
|
||||
@@ -123,9 +69,9 @@ async def classify_intent(state: AgentState) -> AgentState:
|
||||
messages.append(Message(role=msg["role"], content=msg["content"]))
|
||||
|
||||
# Add current message with context
|
||||
user_content = f"用户消息: {state['current_message']}"
|
||||
user_content = f"User message: {state['current_message']}"
|
||||
if context_summary:
|
||||
user_content += f"\n\n当前上下文:\n{context_summary}"
|
||||
user_content += f"\n\nCurrent context:\n{context_summary}"
|
||||
|
||||
messages.append(Message(role="user", content=user_content))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user