feat: 添加 AI Agent 对话测试工具 + 代码优化

主要变更:

- 新增 tests/test_ai_chat.py: AI Agent 对话测试工具

- 优化 core/pydantic_ai_agent.py 和 db/chat_log_db.py

- 清理归档文件,更新文档

Made-with: Cursor
This commit is contained in:
2026-02-28 16:19:35 +08:00
parent a6c42d505a
commit c39840fe15
49 changed files with 2453 additions and 8556 deletions

238
run.py
View File

@@ -1,96 +1,218 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
项目入口 - 启动 WebSocket 客服客户端
AI 客服系统 - 统一启动器
用法:
python run.py # 单进程模式(默认)
python run.py --no-agent # 仅基础回复,不启用 AI
python run.py --multi # 多进程模式
python run.py --multi -w 4 # 多进程模式,指定 4 个进程
python run.py # WebSocket 客服模式(默认)
python run.py --tianwang # 完整版HTTP API + WebSocket + AI Agent
python run.py --tianwang-multi -w 4 # 天网 + 多进程HTTP API + 多进程 WebSocket
python run.py --api-only # 仅 HTTP API不含 WebSocket / AI Agent
python run.py --no-agent # 不启用 AI Agent
python run.py --multi -w 4 # 多进程模式4 个 Worker
python run.py --port 6060 # 指定 HTTP API 端口
"""
import sys
import os
import signal
import logging
import argparse
from pathlib import Path
# 确保项目根目录在 sys.path 首位
_root = Path(__file__).resolve().parent
if str(_root) not in sys.path:
sys.path.insert(0, str(_root))
logging.basicConfig(
level=logging.INFO,
format='[%(asctime)s] %(levelname)s: %(message)s'
)
logger = logging.getLogger(__name__)
def run_single_process(enable_agent: bool):
"""单进程模式"""
from core.websocket_client import QingjianAPIClient
DEFAULT_HTTP_PORT = 6060
def _print_api_info(port: int):
logger.info(f"HTTP API 服务器已启动http://0.0.0.0:{port}")
logger.info("")
logger.info("天网任务接口:")
logger.info(" POST /api/task/receive - 接收任务")
logger.info(" POST /api/task/cancel - 取消任务")
logger.info(" GET /api/task/status/:id - 查询任务状态")
logger.info(" GET /api/task/list - 任务列表")
logger.info(" GET /api/health - 健康检查")
def run_websocket(enable_agent: bool):
"""WebSocket 客服模式(默认)"""
import asyncio
print("=" * 60)
print("AI 客服系统 - 单进程模式")
print("=" * 60)
print(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
print("=" * 60)
from core.websocket_client import QingjianAPIClient
logger.info("=" * 60)
logger.info("AI 客服系统 - WebSocket 模式")
logger.info(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
logger.info("=" * 60)
client = QingjianAPIClient(enable_agent=enable_agent)
try:
asyncio.run(client.run())
except KeyboardInterrupt:
print("\n已停止")
logger.info("已停止")
def run_tianwang(enable_agent: bool, port: int):
"""完整版: HTTP API + WebSocket + AI Agent"""
import asyncio
from api.http_server import start_http_server
from core.websocket_client import QingjianAPIClient
logger.info("=" * 60)
logger.info("AI 客服系统 - 天网协作版(完整)")
logger.info("=" * 60)
start_http_server(host='0.0.0.0', port=port)
_print_api_info(port)
logger.info("=" * 60)
logger.info("正在连接轻简 API...")
client = QingjianAPIClient(enable_agent=enable_agent)
logger.info(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
logger.info("=" * 60)
logger.info("系统已就绪,等待消息和任务...")
def _signal_handler(signum, frame):
logger.info("收到退出信号,正在停止...")
if hasattr(client, 'task_scheduler'):
asyncio.run(client.task_scheduler.stop())
sys.exit(0)
signal.signal(signal.SIGINT, _signal_handler)
signal.signal(signal.SIGTERM, _signal_handler)
try:
asyncio.run(client.connect())
except KeyboardInterrupt:
logger.info("已停止")
except Exception as e:
logger.error(f"运行异常:{e}")
sys.exit(1)
def run_api_only(port: int):
"""仅 HTTP API不含 WebSocket / AI Agent"""
import time
from api.http_server import start_http_server
logger.info("=" * 60)
logger.info("AI 客服系统 - 天网协作版(仅 API")
logger.info("=" * 60)
start_http_server(host='0.0.0.0', port=port)
_print_api_info(port)
logger.info("=" * 60)
logger.info("系统已就绪,等待天网任务...")
def _signal_handler(signum, frame):
logger.info("收到退出信号")
sys.exit(0)
signal.signal(signal.SIGINT, _signal_handler)
signal.signal(signal.SIGTERM, _signal_handler)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
logger.info("已停止")
def run_multi_process(num_workers: int, enable_agent: bool):
"""多进程模式"""
from scripts.multi_process_launcher import Coordinator
print("=" * 60)
print("AI 客服系统 - 多进程异步并行模式")
print("=" * 60)
print(f"工作进程数:{num_workers}")
print(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
print("=" * 60)
coordinator = Coordinator(num_workers=num_workers)
logger.info("=" * 60)
logger.info("AI 客服系统 - 多进程异步并行模式")
logger.info(f"工作进程数:{num_workers}")
logger.info(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
logger.info("=" * 60)
coordinator = Coordinator(num_workers=num_workers, enable_agent=enable_agent)
try:
coordinator.start()
except KeyboardInterrupt:
print("\n已停止")
logger.info("已停止")
coordinator.stop()
def run_tianwang_multi(num_workers: int, enable_agent: bool, port: int):
"""天网 + 多进程HTTP API + 多进程 WebSocket 客户端"""
from api.http_server import start_http_server
from scripts.multi_process_launcher import Coordinator
logger.info("=" * 60)
logger.info("AI 客服系统 - 天网协作版HTTP API + 多进程模式")
logger.info("=" * 60)
start_http_server(host='0.0.0.0', port=port)
_print_api_info(port)
logger.info("=" * 60)
logger.info(f"工作进程数:{num_workers}")
logger.info(f"AI Agent: {'已启用' if enable_agent else '未启用'}")
logger.info("=" * 60)
coordinator = Coordinator(num_workers=num_workers or 0, enable_agent=enable_agent)
def _signal_handler(signum, frame):
logger.info("收到退出信号,正在停止多进程协调器...")
coordinator.stop()
sys.exit(0)
signal.signal(signal.SIGINT, _signal_handler)
signal.signal(signal.SIGTERM, _signal_handler)
try:
coordinator.start()
except KeyboardInterrupt:
logger.info("已停止")
coordinator.stop()
def main():
parser = argparse.ArgumentParser(description='AI 客服系统启动器')
parser.add_argument(
'--no-agent',
action='store_true',
help='不启用 AI Agent仅基础回复'
parser = argparse.ArgumentParser(
description='AI 客服系统启动器',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
启动模式:
(默认) WebSocket 客服模式
--tianwang HTTP API + WebSocket天网完整版
--tianwang-multi HTTP API + 多进程 WebSocket
--api-only 仅 HTTP API不含 WebSocket / AI Agent
--multi 多进程模式
"""
)
parser.add_argument(
'--multi',
action='store_true',
help='多进程模式'
)
parser.add_argument(
'-w', '--workers',
type=int,
default=None,
help='工作进程数默认CPU 核心数,仅多进程模式有效)'
)
mode = parser.add_mutually_exclusive_group()
mode.add_argument('--tianwang', action='store_true', help='天网完整版HTTP API + WebSocket')
mode.add_argument('--tianwang-multi', action='store_true', help='天网 + 多进程HTTP API + 多进程 WebSocket')
mode.add_argument('--api-only', action='store_true', help='仅 HTTP API不含 WebSocket / AI Agent')
mode.add_argument('--multi', action='store_true', help='多进程模式')
parser.add_argument('--no-agent', action='store_true', help='不启用 AI Agent')
parser.add_argument('--port', '-p', type=int, default=DEFAULT_HTTP_PORT, help=f'HTTP API 端口(默认 {DEFAULT_HTTP_PORT}')
parser.add_argument('--workers', '-w', type=int, default=None, help='工作进程数(仅多进程模式,默认 CPU 核心数)')
args = parser.parse_args()
enable_agent = not args.no_agent
if args.multi:
# 多进程模式
run_multi_process(
num_workers=args.workers,
enable_agent=enable_agent
)
if args.api_only:
run_api_only(port=args.port)
elif args.tianwang:
run_tianwang(enable_agent=enable_agent, port=args.port)
elif args.tianwang_multi:
run_tianwang_multi(num_workers=args.workers, enable_agent=enable_agent, port=args.port)
elif args.multi:
run_multi_process(num_workers=args.workers, enable_agent=enable_agent)
else:
# 单进程模式(默认)
run_single_process(enable_agent=enable_agent)
run_websocket(enable_agent=enable_agent)
if __name__ == "__main__":