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:
wangliang
2026-01-16 16:28:47 +08:00
parent 0e59f3067e
commit e093995368
48 changed files with 5263 additions and 395 deletions

74
tests/test_all_faq.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/bin/bash
# 测试所有 FAQ 分类
echo "=========================================="
echo "🧪 测试所有 FAQ 分类"
echo "=========================================="
echo ""
# 定义测试用例
declare -A TEST_CASES=(
["订单相关"]="How do I place an order?"
["支付相关"]="What payment methods do you accept?"
["运输相关"]="What are the shipping options?"
["退货相关"]="I received a defective item, what should I do?"
["账号相关"]="I forgot my password, now what?"
["营业时间"]="What are your opening hours?"
)
# 测试每个分类
for category in "${!TEST_CASES[@]}"; do
question="${TEST_CASES[$category]}"
conv_id="test_${category}___$(date +%s)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📋 分类: $category"
echo "📝 问题: $question"
echo "⏳ 处理中..."
echo ""
# 调用 API
RESPONSE=$(docker exec ai_agent curl -s -X POST 'http://localhost:8000/api/agent/query' \
-H 'Content-Type: application/json' \
-d "{\"conversation_id\":\"$conv_id\",\"user_id\":\"test_user\",\"account_id\":\"2\",\"message\":\"$question\"}")
# 解析并显示结果
echo "$RESPONSE" | python3 << PYTHON
import json
import sys
try:
data = json.load(sys.stdin)
# 提取响应
response = data.get("response", "")
intent = data.get("intent", "")
if response:
# 清理 HTML 标签(如果有)
import re
clean_response = re.sub(r'<[^<]+?>', '', response)
clean_response = clean_response.strip()
# 截断过长响应
if len(clean_response) > 300:
clean_response = clean_response[:300] + "..."
print(f"🎯 意图: {intent}")
print(f"🤖 回答: {clean_response}")
else:
print("❌ 未获得回答")
print(f"调试信息: {json.dumps(data, indent=2, ensure_ascii=False)}")
except Exception as e:
print(f"❌ 解析错误: {e}")
print(f"原始响应: {sys.stdin.read()}")
PYTHON
echo ""
sleep 2 # 间隔 2 秒
done
echo "=========================================="
echo "✅ 所有测试完成"
echo "=========================================="

View File

@@ -0,0 +1,103 @@
"""
测试商城订单查询接口
Usage:
python test_mall_order_query.py <order_id>
Example:
python test_mall_order_query.py 202071324
"""
import asyncio
import sys
import os
# Add mcp_servers to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "mcp_servers"))
from shared.mall_client import MallClient
async def test_order_query(order_id: str, token: str):
"""测试订单查询
Args:
order_id: 订单号
token: JWT Token
"""
print(f"\n{'='*60}")
print(f"测试商城订单查询接口")
print(f"{'='*60}")
print(f"订单号 (Order ID): {order_id}")
print(f"API URL: https://apicn.qa1.gaia888.com")
print(f"{'='*60}\n")
# 创建客户端
client = MallClient(
api_url="https://apicn.qa1.gaia888.com",
api_token=token,
tenant_id="2",
currency_code="EUR",
language_id="1",
source="us.qa1.gaia888.com"
)
try:
# 调用订单查询接口
result = await client.get_order_by_id(order_id)
# 打印结果
print("✅ 查询成功 (Query Success)!")
print(f"\n返回数据 (Response Data):")
print("-" * 60)
import json
print(json.dumps(result, ensure_ascii=False, indent=2))
print("-" * 60)
# 提取关键信息
if isinstance(result, dict):
print(f"\n关键信息 (Key Information):")
print(f" 订单号 (Order ID): {result.get('order_id') or result.get('orderId') or order_id}")
print(f" 订单状态 (Status): {result.get('status') or result.get('order_status') or 'N/A'}")
print(f" 订单金额 (Amount): {result.get('total_amount') or result.get('amount') or 'N/A'}")
# 商品信息
items = result.get('items') or result.get('order_items') or result.get('products')
if items:
print(f" 商品数量 (Items): {len(items)}")
except Exception as e:
print(f"❌ 查询失败 (Query Failed): {str(e)}")
import traceback
traceback.print_exc()
finally:
await client.close()
def main():
"""主函数"""
if len(sys.argv) < 2:
print("Usage: python test_mall_order_query.py <order_id> [token]")
print("\nExample:")
print(' python test_mall_order_query.py 202071324')
print(' python test_mall_order_query.py 202071324 "your_jwt_token_here"')
sys.exit(1)
order_id = sys.argv[1]
# 从命令行获取 token如果没有提供则使用默认的测试 token
if len(sys.argv) >= 3:
token = sys.argv[2]
else:
# 使用用户提供的示例 token
token = "eyJ0eXAiOiJqd3QifQ.eyJzdWIiOiIxIiwiaXNzIjoiaHR0cDpcL1wvOiIsImV4cCI6MTc3MDUyMDY2MSwiaWF0IjoxNzY3OTI4NjYxLCJuYmYiOjE3Njc5Mjg2NjEsInVzZXJJZCI6MTAxNDMyLCJ0eXBlIjoyLCJ0ZW5hbnRJZCI6MiwidWlkIjoxMDE0MzIsInMiOiJkM0tZMjMiLCJqdGkiOiI3YjcwYTI2MzYwYjJmMzA3YmQ4YTYzNDAxOGVlNjlmZSJ9.dwiqln19-yAQSJd1w5bxZFrRgyohdAkHa1zW3W7Ov2I"
print("⚠️ 使用默认的测试 token可能已过期")
print(" 如需测试,请提供有效的 token:")
print(f' python {sys.argv[0]} {order_id} "your_jwt_token_here"\n')
# 运行异步测试
asyncio.run(test_order_query(order_id, token))
if __name__ == "__main__":
main()

63
tests/test_return_faq.py Normal file
View File

@@ -0,0 +1,63 @@
"""
测试退货相关 FAQ 回答
"""
import asyncio
import sys
import os
# 添加 agent 目录到路径
sys.path.insert(0, '/app')
from agents.customer_service import customer_service_agent
from core.state import AgentState
async def test_return_faq():
"""测试退货相关 FAQ"""
# 测试问题列表
test_questions = [
"I received a defective item, what should I do?",
"How do I return a product?",
"What is your return policy?",
"I want to get a refund for my order",
]
for question in test_questions:
print(f"\n{'='*60}")
print(f"📝 问题: {question}")
print(f"{'='*60}")
# 初始化状态
state = AgentState(
conversation_id="test_return_001",
user_id="test_user",
account_id="2",
message=question,
history=[],
context={}
)
try:
# 调用客服 Agent
final_state = await customer_service_agent(state)
# 获取响应
response = final_state.get("response", "无响应")
tool_calls = final_state.get("tool_calls", [])
intent = final_state.get("intent")
print(f"\n🎯 意图识别: {intent}")
print(f"\n🤖 AI 回答:")
print(response)
print(f"\n📊 调用的工具: {tool_calls}")
except Exception as e:
print(f"\n❌ 错误: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
print("🧪 测试退货相关 FAQ 回答\n")
asyncio.run(test_return_faq())