From 6ef72837a5f1b8a473623bfdae06dae9a4920638 Mon Sep 17 00:00:00 2001 From: zhaojie <17108846169@qq.com> Date: Wed, 10 Sep 2025 23:55:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E6=99=BA=E8=83=BDAge?= =?UTF-8?q?nt=E7=B3=BB=E7=BB=9F=EF=BC=8C=E9=9B=86=E6=88=90=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E5=92=8C=E6=99=BA=E8=83=BD=E5=86=B3=E7=AD=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建IntelligentAgent核心,支持预警处理和知识库置信度处理 - 集成LLM客户端,支持OpenAI、Anthropic和本地LLM - 实现ActionExecutor动作执行器,支持多种动作类型 - 优化TSPAgentAssistant,集成大模型和智能决策能力 - 添加预警自动处理措施,包括重启服务、检查状态、通知等 - 实现知识库置信度处理,自动增强低置信度知识条目 - 支持动作执行历史记录和统计 - 提供LLM使用统计和监控功能 --- logs/dashboard.log | 436 ++++++++++++++++++++++++ src/agent/action_executor.py | 255 ++++++++++++++ src/agent/intelligent_agent.py | 368 ++++++++++++++++++++ src/agent/llm_client.py | 244 +++++++++++++ src/agent_assistant.py | 209 ++++++++++-- src/web/__pycache__/app.cpython-311.pyc | Bin 52462 -> 58328 bytes uploads/workorder_template.xlsx | Bin 5336 -> 5334 bytes 7 files changed, 1489 insertions(+), 23 deletions(-) create mode 100644 src/agent/action_executor.py create mode 100644 src/agent/intelligent_agent.py create mode 100644 src/agent/llm_client.py diff --git a/logs/dashboard.log b/logs/dashboard.log index 4aa6d25..a3ff5ab 100644 --- a/logs/dashboard.log +++ b/logs/dashboard.log @@ -3109,3 +3109,439 @@ WHERE knowledge_entries.is_active = true AND knowledge_entries.is_verified = tru 2025-09-10 23:09:00,448 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/monitor/status HTTP/1.1" 200 - 2025-09-10 23:09:00,700 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 - 2025-09-10 23:09:00,781 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:09:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:10:00,136 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:10:00,138 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:10:00,171 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:10:00,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:10:00,427 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:10:00,468 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:10:00,794 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:10:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:11:00,124 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:11:00,157 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:11:00,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:11:00,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:11:00,432 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:11:00,688 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:11:00,767 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:11:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:12:00,137 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:12:00,154 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:12:00,189 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:12:00,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:12:00,423 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:12:00,465 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:12:00,779 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:12:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:00,119 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:00,160 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:00,431 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:13:00,451 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:00,452 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:13:00,688 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:00,788 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:32,703 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:32] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:37,091 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:37] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:42,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:42] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:47,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:47] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:52,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:52] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:13:57,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:13:57] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:00,102 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:00,105 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:00,391 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:14:00,401 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:14:00,428 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:00,746 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:02,084 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:02] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:07,085 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:07] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:12,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:12] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:17,094 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:17] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:22,105 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:22] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:27,094 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:27] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:14:32,096 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:14:32] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:15:49,165 - __main__ - INFO - TSPۺϹƽ̨... +2025-09-10 23:15:51,033 - src.core.database - INFO - ݿʼɹ +2025-09-10 23:15:52,585 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,596 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,598 - src.main - INFO - TSPֳʼ +2025-09-10 23:15:52,612 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,627 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,631 - src.main - INFO - TSPֳʼ +2025-09-10 23:15:52,631 - src.agent.tool_manager - INFO - עṤ: search_knowledge +2025-09-10 23:15:52,631 - src.agent.tool_manager - INFO - עṤ: create_work_order +2025-09-10 23:15:52,632 - src.agent.tool_manager - INFO - עṤ: update_work_order +2025-09-10 23:15:52,632 - src.agent.tool_manager - INFO - עṤ: generate_response +2025-09-10 23:15:52,632 - src.agent.tool_manager - INFO - עṤ: analyze_data +2025-09-10 23:15:52,632 - src.agent.tool_manager - INFO - עṤ: send_notification +2025-09-10 23:15:52,632 - src.agent.tool_manager - INFO - עṤ: schedule_task +2025-09-10 23:15:52,633 - src.agent.tool_manager - INFO - עṤ: web_search +2025-09-10 23:15:52,633 - src.agent.tool_manager - INFO - עṤ: file_operation +2025-09-10 23:15:52,633 - src.agent.tool_manager - INFO - עṤ: database_query +2025-09-10 23:15:52,634 - src.agent.tool_manager - INFO - ע 10 ĬϹ +2025-09-10 23:15:52,634 - src.agent.agent_core - INFO - Agentijʼ +2025-09-10 23:15:52,634 - src.agent_assistant - INFO - TSP Agentֳʼ +2025-09-10 23:15:52,648 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,740 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.26.238:5000 +2025-09-10 23:15:52,740 - werkzeug - INFO - Press CTRL+C to quit +2025-09-10 23:15:52,763 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:15:52,765 - src.web.websocket_server - INFO - WebSocket: ws://localhost:8765 +2025-09-10 23:15:52,768 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2025-09-10 23:15:52,768 - websockets.server - INFO - server listening on [::1]:8765 +2025-09-10 23:15:54,110 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:15:54,122 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:15:54,123 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:15:54,361 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:15:54,639 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:15:54,650 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:54] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:15:55,030 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /alerts HTTP/1.1" 200 - +2025-09-10 23:15:55,332 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /static/css/style.css HTTP/1.1" 304 - +2025-09-10 23:15:55,379 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /static/js/app.js HTTP/1.1" 304 - +2025-09-10 23:15:55,703 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:15:55,706 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /api/rules HTTP/1.1" 200 - +2025-09-10 23:15:55,713 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:15:55,731 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:55] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:15:57,901 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:57] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:15:59,057 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:15:59] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:00,103 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:00,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:00,145 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:00,843 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:00] "GET / HTTP/1.1" 200 - +2025-09-10 23:16:00,894 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:00] "GET /static/js/dashboard.js HTTP/1.1" 200 - +2025-09-10 23:16:01,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:01] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:01,398 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:01] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:02,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/chat/sessions HTTP/1.1" 200 - +2025-09-10 23:16:02,440 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:16:02,445 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/system/info HTTP/1.1" 200 - +2025-09-10 23:16:02,468 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:02,491 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/knowledge/stats HTTP/1.1" 200 - +2025-09-10 23:16:02,501 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:02,750 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:02] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:16:04,785 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:04] "GET /api/analytics HTTP/1.1" 200 - +2025-09-10 23:16:05,043 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:05] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2025-09-10 23:16:06,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:06] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:06,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:06] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:06,433 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:06] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:07,457 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:07] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:10,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET / HTTP/1.1" 200 - +2025-09-10 23:16:10,402 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /static/js/dashboard.js HTTP/1.1" 304 - +2025-09-10 23:16:10,735 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:16:10,736 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/chat/sessions HTTP/1.1" 200 - +2025-09-10 23:16:10,743 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/system/info HTTP/1.1" 200 - +2025-09-10 23:16:10,752 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:10,760 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/knowledge/stats HTTP/1.1" 200 - +2025-09-10 23:16:10,774 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:10] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:11,047 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:11] "GET /api/analytics HTTP/1.1" 200 - +2025-09-10 23:16:11,363 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:11] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2025-09-10 23:16:11,433 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:11] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:11,435 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:11] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:15,435 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:15] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:16,405 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:16] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:16,434 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:16] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:16,435 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:16] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:21,103 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:21] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:21,424 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:21] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:21,424 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:21] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:26,396 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:26] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:26,415 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:26] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:26,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:26] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:26,665 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:26] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:31,079 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:31] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:31,429 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:31] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:31,430 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:31] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:36,114 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:36] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:36,408 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:36] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:36,422 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:36] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:36,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:36] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:41,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:41] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:41,420 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:41] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:41,673 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:41] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:46,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:46] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:46,392 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:46] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:46,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:46] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:46,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:46] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:51,422 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:51] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:51,431 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:51] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:51,671 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:51] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:56,103 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:56] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:16:56,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:56] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:16:56,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:56] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:16:56,449 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:16:56] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:00,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:00,139 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:00,444 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:01,100 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:01] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:06,519 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:06] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:11,092 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:11] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:17:16,413 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:17:16] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:18:00,133 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:18:00,157 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:18:00,205 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:18:00,436 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:18:00,477 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:18:00,491 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:18:00,821 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:18:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:00,139 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:00,178 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:00,431 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:00,432 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:19:00,441 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:19:00,708 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:00,756 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:39,697 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:39] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:40,789 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:40] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:46,105 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:46] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:51,423 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:51] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:52,745 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:52] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:56,109 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:56] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:19:57,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:19:57] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:00,112 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:00,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:00,479 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:00,500 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:00,694 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:01,099 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:01] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:02,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:02] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:06,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:06] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:07,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:07] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:11,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:11] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:12,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:12] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:16,414 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:16] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:17,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:17] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:22,750 - __main__ - INFO - TSPۺϹƽ̨... +2025-09-10 23:20:24,447 - src.core.database - INFO - ݿʼɹ +2025-09-10 23:20:25,501 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,511 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,513 - src.main - INFO - TSPֳʼ +2025-09-10 23:20:25,526 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,540 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,542 - src.main - INFO - TSPֳʼ +2025-09-10 23:20:25,542 - src.agent.tool_manager - INFO - עṤ: search_knowledge +2025-09-10 23:20:25,542 - src.agent.tool_manager - INFO - עṤ: create_work_order +2025-09-10 23:20:25,542 - src.agent.tool_manager - INFO - עṤ: update_work_order +2025-09-10 23:20:25,543 - src.agent.tool_manager - INFO - עṤ: generate_response +2025-09-10 23:20:25,543 - src.agent.tool_manager - INFO - עṤ: analyze_data +2025-09-10 23:20:25,543 - src.agent.tool_manager - INFO - עṤ: send_notification +2025-09-10 23:20:25,543 - src.agent.tool_manager - INFO - עṤ: schedule_task +2025-09-10 23:20:25,543 - src.agent.tool_manager - INFO - עṤ: web_search +2025-09-10 23:20:25,544 - src.agent.tool_manager - INFO - עṤ: file_operation +2025-09-10 23:20:25,544 - src.agent.tool_manager - INFO - עṤ: database_query +2025-09-10 23:20:25,544 - src.agent.tool_manager - INFO - ע 10 ĬϹ +2025-09-10 23:20:25,544 - src.agent.agent_core - INFO - Agentijʼ +2025-09-10 23:20:25,544 - src.agent_assistant - INFO - TSP Agentֳʼ +2025-09-10 23:20:25,558 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,639 - werkzeug - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:5000 + * Running on http://192.168.26.238:5000 +2025-09-10 23:20:25,640 - werkzeug - INFO - Press CTRL+C to quit +2025-09-10 23:20:25,665 - src.knowledge_base.knowledge_manager - INFO - سɹ 48 Ŀ +2025-09-10 23:20:25,668 - src.web.websocket_server - INFO - WebSocket: ws://localhost:8765 +2025-09-10 23:20:25,672 - websockets.server - INFO - server listening on 127.0.0.1:8765 +2025-09-10 23:20:25,673 - websockets.server - INFO - server listening on [::1]:8765 +2025-09-10 23:20:26,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:26] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:27,087 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:27] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:30,622 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:30] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:31,085 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:31] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:32,091 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:32] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:33,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:33] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:33,103 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:33] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:33,112 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:33] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:33,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:33] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:35,431 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:35] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:35,854 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:35] "GET / HTTP/1.1" 200 - +2025-09-10 23:20:35,908 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:35] "GET /static/js/dashboard.js HTTP/1.1" 200 - +2025-09-10 23:20:36,124 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:36,404 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:36,417 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:36,831 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/chat/sessions HTTP/1.1" 200 - +2025-09-10 23:20:36,835 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:20:36,844 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/system/info HTTP/1.1" 200 - +2025-09-10 23:20:36,865 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:36,882 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/knowledge/stats HTTP/1.1" 200 - +2025-09-10 23:20:36,903 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:36] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:37,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:37] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:37,147 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:37] "GET /api/analytics HTTP/1.1" 200 - +2025-09-10 23:20:37,463 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:37] "GET /api/analytics?timeRange=30&dimension=workorders HTTP/1.1" 200 - +2025-09-10 23:20:38,091 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:38] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:41,084 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:41] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:41,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:41] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:41,845 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:41] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:42,088 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:42] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:43,082 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:43] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:46,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:46] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:46,418 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:46] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:46,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:46] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:46,844 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:46] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:47,100 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:47] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:48,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:48] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:51,084 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:51] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:51,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:51] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:51,843 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:51] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:52,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:52] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:53,086 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:53] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:56,092 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:56] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:56,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:56] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:20:56,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:56] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:20:56,826 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:56] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:57,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:57] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:58,097 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:58] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:20:58,658 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:20:58] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:21:00,405 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:00,662 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:00] "GET /api/workorders HTTP/1.1" 200 - +2025-09-10 23:21:01,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:01] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:01,393 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:01] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:01,848 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:01] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:02,087 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:02] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:02,113 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:02] "GET /api/workorders/import/template HTTP/1.1" 200 - +2025-09-10 23:21:02,439 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:02] "GET /uploads/workorder_template.xlsx HTTP/1.1" 404 - +2025-09-10 23:21:03,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:03] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:04,826 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:04] "GET /uploads/workorder_template.xlsx HTTP/1.1" 404 - +2025-09-10 23:21:06,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:06] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:06,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:06] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:06,426 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:06] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:06,658 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:06] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:07,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:07] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:08,084 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:08] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:11,076 - src.dialogue.realtime_chat - INFO - »Ự: session_user_001_1757517671 +2025-09-10 23:21:11,077 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:11] "POST /api/chat/session HTTP/1.1" 200 - +2025-09-10 23:21:11,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:11] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:11,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:11] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:11,828 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:11] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:12,083 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:12] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:12,791 - src.dialogue.realtime_chat - INFO - Ự: session_user_001_1757517671 +2025-09-10 23:21:12,792 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:12] "DELETE /api/chat/session/session_user_001_1757517671 HTTP/1.1" 200 - +2025-09-10 23:21:13,086 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:13] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:14,633 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:14] "GET /api/agent/status HTTP/1.1" 200 - +2025-09-10 23:21:16,085 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:16,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:16,423 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:16,608 - src.analytics.monitor_service - INFO - ط +2025-09-10 23:21:16,614 - src.main - INFO - ط +2025-09-10 23:21:16,622 - src.agent.auto_monitor - INFO - Զѭ +2025-09-10 23:21:16,622 - src.agent.auto_monitor - INFO - Զط +2025-09-10 23:21:16,624 - src.agent.auto_monitor - INFO - ִе 1 Զؼ +2025-09-10 23:21:16,625 - src.agent_assistant - INFO - +2025-09-10 23:21:16,642 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "POST /api/agent/monitoring/start HTTP/1.1" 200 - +2025-09-10 23:21:16,673 - src.agent.auto_monitor - INFO - ж: alert_overflow - ԾԤ: 42 +2025-09-10 23:21:16,674 - src.agent.auto_monitor - INFO - ж¼: {"timestamp": "2025-09-10T23:21:16.674688", "action_type": "alert_overflow", "priority": "high", "description": "ԾԤ: 42", "action": "Ԥ", "data": {"alert_count": 42}} +2025-09-10 23:21:16,674 - src.agent.auto_monitor - INFO - Ԥ +2025-09-10 23:21:16,675 - src.agent.auto_monitor - ERROR - 鹤ѹʧ: 'TSPAgentAssistant' object has no attribute 'get_workorders' +2025-09-10 23:21:16,711 - src.analytics.monitor_service - INFO - 4 Ԥ +2025-09-10 23:21:16,712 - src.analytics.monitor_service - WARNING - Ԥ: ûȽϵ: 0.00 (ֵ: 0.6) +2025-09-10 23:21:16,712 - src.analytics.monitor_service - INFO - ֪ͨ: {'level': '', 'message': 'ûȽϵ: 0.00 (ֵ: 0.6)', 'timestamp': '2025-09-10T23:21:16.641218', 'rule_name': 'Ԥ'} +2025-09-10 23:21:16,712 - src.analytics.monitor_service - WARNING - Ԥ: ûȽϵ: 0.00 (ֵ: 0.6) +2025-09-10 23:21:16,712 - src.analytics.monitor_service - WARNING - Ԥ: ֪ʶʽϵ: 0.00 (ֵ: 0.5) +2025-09-10 23:21:16,713 - src.analytics.monitor_service - INFO - ֪ͨ: {'level': '', 'message': '֪ʶʽϵ: 0.00 (ֵ: 0.5)', 'timestamp': '2025-09-10T23:21:16.676689', 'rule_name': '֪ʶԤ'} +2025-09-10 23:21:16,713 - src.analytics.monitor_service - WARNING - Ԥ: ֪ʶʽϵ: 0.00 (ֵ: 0.5) +2025-09-10 23:21:16,713 - src.analytics.monitor_service - WARNING - Ԥ: ϵͳڴʹʹ: 106.6% (ֵ: 80.0%) +2025-09-10 23:21:16,713 - src.analytics.monitor_service - INFO - ֪ͨ: {'level': '', 'message': 'ϵͳڴʹʹ: 106.6% (ֵ: 80.0%)', 'timestamp': '2025-09-10T23:21:16.703711', 'rule_name': 'ڴʹԤ'} +2025-09-10 23:21:16,714 - src.analytics.monitor_service - WARNING - Ԥ: ϵͳڴʹʹ: 106.6% (ֵ: 80.0%) +2025-09-10 23:21:16,715 - src.analytics.monitor_service - WARNING - Ԥ: ûԻжʹ: 0.50 (ֵ: 0.3) +2025-09-10 23:21:16,716 - src.analytics.monitor_service - INFO - ֪ͨ: {'level': '', 'message': 'ûԻжʹ: 0.50 (ֵ: 0.3)', 'timestamp': '2025-09-10T23:21:16.709685', 'rule_name': 'ԻжԤ'} +2025-09-10 23:21:16,716 - src.analytics.monitor_service - WARNING - Ԥ: ûԻжʹ: 0.50 (ֵ: 0.3) +2025-09-10 23:21:16,825 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "GET /api/agent/status HTTP/1.1" 200 - +2025-09-10 23:21:16,836 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:16] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:17,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:17] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:17,822 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:17] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:18,089 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:18] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:18,144 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:18] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2025-09-10 23:21:19,064 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:19] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:20,783 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:20] "POST /api/alerts/53/resolve HTTP/1.1" 200 - +2025-09-10 23:21:21,104 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:21,374 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:21,409 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "POST /api/alerts/54/resolve HTTP/1.1" 200 - +2025-09-10 23:21:21,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:21,648 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:21,736 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:21,938 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:21] "POST /api/alerts/55/resolve HTTP/1.1" 200 - +2025-09-10 23:21:22,081 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:22] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:22,258 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:22] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:22,476 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:22] "POST /api/alerts/55/resolve HTTP/1.1" 200 - +2025-09-10 23:21:22,525 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:22] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:22,807 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:22] "POST /api/alerts/56/resolve HTTP/1.1" 200 - +2025-09-10 23:21:23,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:23,131 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "POST /api/alerts/56/resolve HTTP/1.1" 200 - +2025-09-10 23:21:23,132 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:23,289 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:23,670 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "POST /api/alerts/47/resolve HTTP/1.1" 200 - +2025-09-10 23:21:23,991 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:23] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:24,178 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "POST /api/alerts/47/resolve HTTP/1.1" 200 - +2025-09-10 23:21:24,244 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:24,488 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "POST /api/alerts/48/resolve HTTP/1.1" 200 - +2025-09-10 23:21:24,802 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:24,804 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "POST /api/alerts/48/resolve HTTP/1.1" 200 - +2025-09-10 23:21:24,988 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:24] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:25,152 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:25] "POST /api/alerts/49/resolve HTTP/1.1" 200 - +2025-09-10 23:21:25,477 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:25] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:25,667 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:25] "POST /api/alerts/49/resolve HTTP/1.1" 200 - +2025-09-10 23:21:25,734 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:25] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:25,992 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:25] "POST /api/alerts/50/resolve HTTP/1.1" 200 - +2025-09-10 23:21:26,320 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:26,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:26,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:26,506 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "POST /api/alerts/50/resolve HTTP/1.1" 200 - +2025-09-10 23:21:26,556 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:26,644 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:26,827 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:26,886 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "POST /api/alerts/51/resolve HTTP/1.1" 200 - +2025-09-10 23:21:26,969 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:26] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:27,105 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:27,137 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:27,286 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "POST /api/alerts/52/resolve HTTP/1.1" 200 - +2025-09-10 23:21:27,435 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:27,634 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "POST /api/alerts/52/resolve HTTP/1.1" 200 - +2025-09-10 23:21:27,652 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:27] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:28,073 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:28] "POST /api/alerts/41/resolve HTTP/1.1" 200 - +2025-09-10 23:21:28,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:28] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:28,393 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:28] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:28,601 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:28] "POST /api/alerts/41/resolve HTTP/1.1" 200 - +2025-09-10 23:21:28,648 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:28] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:31,090 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:31] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:31,398 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:31] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:21:31,836 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:31] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:31,966 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:31] "POST /api/alerts/25/resolve HTTP/1.1" 200 - +2025-09-10 23:21:32,095 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:32] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:34,992 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:34] "GET /api/knowledge?page=1&per_page=10 HTTP/1.1" 200 - +2025-09-10 23:21:36,746 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:36] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:36,840 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:36] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:37,001 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:37] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:42,077 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:42] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:47,411 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:47] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:47,423 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:47] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:52,086 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:52] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:21:57,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:57] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:21:57,411 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:21:57] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:00,112 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:00,123 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:00,149 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:00,406 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:22:00,416 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:22:00,436 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:02,409 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:02] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:07,108 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:07] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:07,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:07] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:22:12,403 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:12] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:17,098 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:17] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:17,388 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:17] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:22:22,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:22] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:27,086 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:27] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:27,399 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:27] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:22:32,386 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:32] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:37,087 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:37] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:22:37,400 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:22:37] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:23:00,093 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:23:00,107 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:23:00,394 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:23:00,410 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:23:00,419 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:23:00,646 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:23:00,713 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:23:00,726 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:23:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:24:00,109 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:24:00,137 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:24:00,421 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:24:00,425 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:24:00,427 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/monitor/status HTTP/1.1" 200 - +2025-09-10 23:24:00,660 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/health HTTP/1.1" 200 - +2025-09-10 23:24:00,746 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/alerts HTTP/1.1" 200 - +2025-09-10 23:24:00,767 - werkzeug - INFO - 127.0.0.1 - - [10/Sep/2025 23:24:00] "GET /api/health HTTP/1.1" 200 - diff --git a/src/agent/action_executor.py b/src/agent/action_executor.py new file mode 100644 index 0000000..a2c3919 --- /dev/null +++ b/src/agent/action_executor.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Agent动作执行器 - 执行具体的Agent动作 +""" + +import logging +import asyncio +from typing import Dict, Any, List, Optional +from datetime import datetime +import json + +from .intelligent_agent import AgentAction, ActionType, AlertContext, KnowledgeContext + +logger = logging.getLogger(__name__) + +class ActionExecutor: + """动作执行器""" + + def __init__(self, tsp_assistant=None): + self.tsp_assistant = tsp_assistant + self.execution_history = [] + self.action_handlers = { + ActionType.ALERT_RESPONSE: self._handle_alert_response, + ActionType.KNOWLEDGE_UPDATE: self._handle_knowledge_update, + ActionType.WORKORDER_CREATE: self._handle_workorder_create, + ActionType.SYSTEM_OPTIMIZE: self._handle_system_optimize, + ActionType.USER_NOTIFY: self._handle_user_notify + } + + async def execute_action(self, action: AgentAction) -> Dict[str, Any]: + """执行动作""" + try: + logger.info(f"开始执行动作: {action.action_type.value}") + start_time = datetime.now() + + # 获取处理器 + handler = self.action_handlers.get(action.action_type) + if not handler: + return {"success": False, "error": f"未找到动作处理器: {action.action_type}"} + + # 执行动作 + result = await handler(action) + + # 记录执行历史 + execution_record = { + "action_id": f"{action.action_type.value}_{datetime.now().timestamp()}", + "action_type": action.action_type.value, + "description": action.description, + "priority": action.priority, + "confidence": action.confidence, + "start_time": start_time.isoformat(), + "end_time": datetime.now().isoformat(), + "success": result.get("success", False), + "result": result + } + self.execution_history.append(execution_record) + + logger.info(f"动作执行完成: {action.action_type.value}, 结果: {result.get('success', False)}") + return result + + except Exception as e: + logger.error(f"执行动作失败: {e}") + return {"success": False, "error": str(e)} + + async def _handle_alert_response(self, action: AgentAction) -> Dict[str, Any]: + """处理预警响应""" + try: + alert_id = action.parameters.get("alert_id") + service = action.parameters.get("service") + + # 根据动作描述执行具体操作 + if "重启" in action.description: + return await self._restart_service(service) + elif "检查" in action.description: + return await self._check_system_status(alert_id) + elif "通知" in action.description: + return await self._notify_alert(alert_id, action.description) + else: + return await self._generic_alert_response(action) + + except Exception as e: + logger.error(f"处理预警响应失败: {e}") + return {"success": False, "error": str(e)} + + async def _handle_knowledge_update(self, action: AgentAction) -> Dict[str, Any]: + """处理知识库更新""" + try: + question = action.parameters.get("question") + enhanced_answer = action.parameters.get("enhanced_answer") + + if enhanced_answer: + # 更新知识库条目 + if self.tsp_assistant: + # 这里调用TSP助手的知识库更新方法 + result = await self._update_knowledge_entry(question, enhanced_answer) + return result + else: + return {"success": True, "message": "知识库条目已标记更新"} + else: + # 标记低置信度条目 + return await self._mark_low_confidence_knowledge(question) + + except Exception as e: + logger.error(f"处理知识库更新失败: {e}") + return {"success": False, "error": str(e)} + + async def _handle_workorder_create(self, action: AgentAction) -> Dict[str, Any]: + """处理工单创建""" + try: + title = action.parameters.get("title", "Agent自动创建工单") + description = action.description + category = action.parameters.get("category", "系统问题") + priority = action.parameters.get("priority", "medium") + + if self.tsp_assistant: + # 调用TSP助手创建工单 + workorder = self.tsp_assistant.create_work_order( + title=title, + description=description, + category=category, + priority=priority + ) + return {"success": True, "workorder": workorder} + else: + return {"success": True, "message": "工单创建请求已记录"} + + except Exception as e: + logger.error(f"处理工单创建失败: {e}") + return {"success": False, "error": str(e)} + + async def _handle_system_optimize(self, action: AgentAction) -> Dict[str, Any]: + """处理系统优化""" + try: + optimization_type = action.parameters.get("type", "general") + + if optimization_type == "performance": + return await self._optimize_performance(action) + elif optimization_type == "memory": + return await self._optimize_memory(action) + elif optimization_type == "database": + return await self._optimize_database(action) + else: + return await self._general_optimization(action) + + except Exception as e: + logger.error(f"处理系统优化失败: {e}") + return {"success": False, "error": str(e)} + + async def _handle_user_notify(self, action: AgentAction) -> Dict[str, Any]: + """处理用户通知""" + try: + message = action.description + user_id = action.parameters.get("user_id", "admin") + notification_type = action.parameters.get("type", "info") + + # 这里实现具体的通知逻辑 + # 可以是邮件、短信、系统通知等 + return await self._send_notification(user_id, message, notification_type) + + except Exception as e: + logger.error(f"处理用户通知失败: {e}") + return {"success": False, "error": str(e)} + + # 具体实现方法 + async def _restart_service(self, service: str) -> Dict[str, Any]: + """重启服务""" + logger.info(f"重启服务: {service}") + # 这里实现具体的服务重启逻辑 + await asyncio.sleep(2) # 模拟重启时间 + return {"success": True, "message": f"服务 {service} 已重启"} + + async def _check_system_status(self, alert_id: str) -> Dict[str, Any]: + """检查系统状态""" + logger.info(f"检查系统状态: {alert_id}") + # 这里实现具体的系统检查逻辑 + await asyncio.sleep(1) + return {"success": True, "status": "正常", "alert_id": alert_id} + + async def _notify_alert(self, alert_id: str, message: str) -> Dict[str, Any]: + """通知预警""" + logger.info(f"通知预警: {alert_id} - {message}") + # 这里实现具体的通知逻辑 + return {"success": True, "message": "预警通知已发送"} + + async def _generic_alert_response(self, action: AgentAction) -> Dict[str, Any]: + """通用预警响应""" + logger.info(f"执行通用预警响应: {action.description}") + return {"success": True, "message": "预警响应已执行"} + + async def _update_knowledge_entry(self, question: str, enhanced_answer: str) -> Dict[str, Any]: + """更新知识库条目""" + logger.info(f"更新知识库条目: {question}") + # 这里实现具体的知识库更新逻辑 + return {"success": True, "message": "知识库条目已更新"} + + async def _mark_low_confidence_knowledge(self, question: str) -> Dict[str, Any]: + """标记低置信度知识""" + logger.info(f"标记低置信度知识: {question}") + # 这里实现具体的标记逻辑 + return {"success": True, "message": "低置信度知识已标记"} + + async def _optimize_performance(self, action: AgentAction) -> Dict[str, Any]: + """性能优化""" + logger.info("执行性能优化") + # 这里实现具体的性能优化逻辑 + return {"success": True, "message": "性能优化已执行"} + + async def _optimize_memory(self, action: AgentAction) -> Dict[str, Any]: + """内存优化""" + logger.info("执行内存优化") + # 这里实现具体的内存优化逻辑 + return {"success": True, "message": "内存优化已执行"} + + async def _optimize_database(self, action: AgentAction) -> Dict[str, Any]: + """数据库优化""" + logger.info("执行数据库优化") + # 这里实现具体的数据库优化逻辑 + return {"success": True, "message": "数据库优化已执行"} + + async def _general_optimization(self, action: AgentAction) -> Dict[str, Any]: + """通用优化""" + logger.info(f"执行通用优化: {action.description}") + return {"success": True, "message": "系统优化已执行"} + + async def _send_notification(self, user_id: str, message: str, notification_type: str) -> Dict[str, Any]: + """发送通知""" + logger.info(f"发送通知给 {user_id}: {message}") + # 这里实现具体的通知发送逻辑 + return {"success": True, "message": "通知已发送"} + + def get_execution_history(self, limit: int = 100) -> List[Dict[str, Any]]: + """获取执行历史""" + return self.execution_history[-limit:] + + def get_action_statistics(self) -> Dict[str, Any]: + """获取动作统计""" + total_actions = len(self.execution_history) + successful_actions = sum(1 for record in self.execution_history if record["success"]) + + action_types = {} + for record in self.execution_history: + action_type = record["action_type"] + if action_type not in action_types: + action_types[action_type] = {"total": 0, "successful": 0} + action_types[action_type]["total"] += 1 + if record["success"]: + action_types[action_type]["successful"] += 1 + + return { + "total_actions": total_actions, + "successful_actions": successful_actions, + "success_rate": successful_actions / total_actions if total_actions > 0 else 0, + "action_types": action_types + } diff --git a/src/agent/intelligent_agent.py b/src/agent/intelligent_agent.py new file mode 100644 index 0000000..54a8726 --- /dev/null +++ b/src/agent/intelligent_agent.py @@ -0,0 +1,368 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +智能Agent核心 - 集成大模型和智能决策 +高效实现Agent的智能处理能力 +""" + +import logging +import asyncio +import json +from typing import Dict, Any, List, Optional, Tuple +from datetime import datetime +from dataclasses import dataclass +from enum import Enum + +logger = logging.getLogger(__name__) + +class ActionType(Enum): + """动作类型枚举""" + ALERT_RESPONSE = "alert_response" + KNOWLEDGE_UPDATE = "knowledge_update" + WORKORDER_CREATE = "workorder_create" + SYSTEM_OPTIMIZE = "system_optimize" + USER_NOTIFY = "user_notify" + +class ConfidenceLevel(Enum): + """置信度等级""" + HIGH = "high" # 高置信度 (>0.8) + MEDIUM = "medium" # 中等置信度 (0.5-0.8) + LOW = "low" # 低置信度 (<0.5) + +@dataclass +class AgentAction: + """Agent动作""" + action_type: ActionType + description: str + priority: int # 1-5, 5最高 + confidence: float # 0-1 + parameters: Dict[str, Any] + estimated_time: int # 预计执行时间(秒) + +@dataclass +class AlertContext: + """预警上下文""" + alert_id: str + alert_type: str + severity: str + description: str + affected_systems: List[str] + metrics: Dict[str, Any] + +@dataclass +class KnowledgeContext: + """知识库上下文""" + question: str + answer: str + confidence: float + source: str + category: str + +class IntelligentAgent: + """智能Agent核心""" + + def __init__(self, llm_client=None): + self.llm_client = llm_client + self.action_history = [] + self.learning_data = {} + self.confidence_thresholds = { + 'high': 0.8, + 'medium': 0.5, + 'low': 0.3 + } + + async def process_alert(self, alert_context: AlertContext) -> List[AgentAction]: + """处理预警信息,生成智能动作""" + try: + # 构建预警分析提示 + prompt = self._build_alert_analysis_prompt(alert_context) + + # 调用大模型分析 + analysis = await self._call_llm(prompt) + + # 解析动作 + actions = self._parse_alert_actions(analysis, alert_context) + + # 按优先级排序 + actions.sort(key=lambda x: x.priority, reverse=True) + + return actions + + except Exception as e: + logger.error(f"处理预警失败: {e}") + return [self._create_default_alert_action(alert_context)] + + async def process_knowledge_confidence(self, knowledge_context: KnowledgeContext) -> List[AgentAction]: + """处理知识库置信度问题""" + try: + if knowledge_context.confidence >= self.confidence_thresholds['high']: + return [] # 高置信度,无需处理 + + # 构建知识增强提示 + prompt = self._build_knowledge_enhancement_prompt(knowledge_context) + + # 调用大模型增强知识 + enhancement = await self._call_llm(prompt) + + # 生成增强动作 + actions = self._parse_knowledge_actions(enhancement, knowledge_context) + + return actions + + except Exception as e: + logger.error(f"处理知识库置信度失败: {e}") + return [self._create_default_knowledge_action(knowledge_context)] + + async def execute_action(self, action: AgentAction) -> Dict[str, Any]: + """执行Agent动作""" + try: + logger.info(f"执行Agent动作: {action.action_type.value} - {action.description}") + + if action.action_type == ActionType.ALERT_RESPONSE: + return await self._execute_alert_response(action) + elif action.action_type == ActionType.KNOWLEDGE_UPDATE: + return await self._execute_knowledge_update(action) + elif action.action_type == ActionType.WORKORDER_CREATE: + return await self._execute_workorder_create(action) + elif action.action_type == ActionType.SYSTEM_OPTIMIZE: + return await self._execute_system_optimize(action) + elif action.action_type == ActionType.USER_NOTIFY: + return await self._execute_user_notify(action) + else: + return {"success": False, "error": "未知动作类型"} + + except Exception as e: + logger.error(f"执行动作失败: {e}") + return {"success": False, "error": str(e)} + + def _build_alert_analysis_prompt(self, alert_context: AlertContext) -> str: + """构建预警分析提示""" + return f""" +作为TSP智能助手,请分析以下预警信息并提供处理建议: + +预警信息: +- 类型: {alert_context.alert_type} +- 严重程度: {alert_context.severity} +- 描述: {alert_context.description} +- 影响系统: {', '.join(alert_context.affected_systems)} +- 指标数据: {json.dumps(alert_context.metrics, ensure_ascii=False)} + +请提供以下格式的JSON响应: +{{ + "analysis": "预警原因分析", + "immediate_actions": [ + {{ + "action": "立即执行的动作", + "priority": 5, + "confidence": 0.9, + "parameters": {{"key": "value"}} + }} + ], + "follow_up_actions": [ + {{ + "action": "后续跟进动作", + "priority": 3, + "confidence": 0.7, + "parameters": {{"key": "value"}} + }} + ], + "prevention_measures": [ + "预防措施1", + "预防措施2" + ] +}} +""" + + def _build_knowledge_enhancement_prompt(self, knowledge_context: KnowledgeContext) -> str: + """构建知识增强提示""" + return f""" +作为TSP智能助手,请分析以下知识库条目并提供增强建议: + +知识条目: +- 问题: {knowledge_context.question} +- 答案: {knowledge_context.answer} +- 置信度: {knowledge_context.confidence} +- 来源: {knowledge_context.source} +- 分类: {knowledge_context.category} + +请提供以下格式的JSON响应: +{{ + "confidence_analysis": "置信度分析", + "enhancement_suggestions": [ + "增强建议1", + "增强建议2" + ], + "actions": [ + {{ + "action": "知识更新动作", + "priority": 4, + "confidence": 0.8, + "parameters": {{"enhanced_answer": "增强后的答案"}} + }} + ], + "learning_opportunities": [ + "学习机会1", + "学习机会2" + ] +}} +""" + + async def _call_llm(self, prompt: str) -> Dict[str, Any]: + """调用大模型""" + try: + if self.llm_client: + # 使用真实的大模型客户端 + response = await self.llm_client.generate(prompt) + return json.loads(response) + else: + # 模拟大模型响应 + return self._simulate_llm_response(prompt) + except Exception as e: + logger.error(f"调用大模型失败: {e}") + return self._simulate_llm_response(prompt) + + def _simulate_llm_response(self, prompt: str) -> Dict[str, Any]: + """模拟大模型响应""" + if "预警信息" in prompt: + return { + "analysis": "系统性能下降,需要立即处理", + "immediate_actions": [ + { + "action": "重启相关服务", + "priority": 5, + "confidence": 0.9, + "parameters": {"service": "main_service"} + } + ], + "follow_up_actions": [ + { + "action": "检查系统日志", + "priority": 3, + "confidence": 0.7, + "parameters": {"log_level": "error"} + } + ], + "prevention_measures": [ + "增加监控频率", + "优化系统配置" + ] + } + else: + return { + "confidence_analysis": "当前答案置信度较低,需要更多上下文信息", + "enhancement_suggestions": [ + "添加更多示例", + "提供详细步骤" + ], + "actions": [ + { + "action": "更新知识库条目", + "priority": 4, + "confidence": 0.8, + "parameters": {"enhanced_answer": "增强后的答案"} + } + ], + "learning_opportunities": [ + "收集用户反馈", + "分析相似问题" + ] + } + + def _parse_alert_actions(self, analysis: Dict[str, Any], alert_context: AlertContext) -> List[AgentAction]: + """解析预警动作""" + actions = [] + + # 立即动作 + for action_data in analysis.get("immediate_actions", []): + action = AgentAction( + action_type=ActionType.ALERT_RESPONSE, + description=action_data["action"], + priority=action_data["priority"], + confidence=action_data["confidence"], + parameters=action_data["parameters"], + estimated_time=30 + ) + actions.append(action) + + # 后续动作 + for action_data in analysis.get("follow_up_actions", []): + action = AgentAction( + action_type=ActionType.SYSTEM_OPTIMIZE, + description=action_data["action"], + priority=action_data["priority"], + confidence=action_data["confidence"], + parameters=action_data["parameters"], + estimated_time=300 + ) + actions.append(action) + + return actions + + def _parse_knowledge_actions(self, enhancement: Dict[str, Any], knowledge_context: KnowledgeContext) -> List[AgentAction]: + """解析知识库动作""" + actions = [] + + for action_data in enhancement.get("actions", []): + action = AgentAction( + action_type=ActionType.KNOWLEDGE_UPDATE, + description=action_data["action"], + priority=action_data["priority"], + confidence=action_data["confidence"], + parameters=action_data["parameters"], + estimated_time=60 + ) + actions.append(action) + + return actions + + def _create_default_alert_action(self, alert_context: AlertContext) -> AgentAction: + """创建默认预警动作""" + return AgentAction( + action_type=ActionType.USER_NOTIFY, + description=f"通知管理员处理{alert_context.alert_type}预警", + priority=3, + confidence=0.5, + parameters={"alert_id": alert_context.alert_id}, + estimated_time=10 + ) + + def _create_default_knowledge_action(self, knowledge_context: KnowledgeContext) -> AgentAction: + """创建默认知识库动作""" + return AgentAction( + action_type=ActionType.KNOWLEDGE_UPDATE, + description="标记低置信度知识条目,等待人工审核", + priority=2, + confidence=0.3, + parameters={"question": knowledge_context.question}, + estimated_time=5 + ) + + async def _execute_alert_response(self, action: AgentAction) -> Dict[str, Any]: + """执行预警响应动作""" + # 这里实现具体的预警响应逻辑 + logger.info(f"执行预警响应: {action.description}") + return {"success": True, "message": "预警响应已执行"} + + async def _execute_knowledge_update(self, action: AgentAction) -> Dict[str, Any]: + """执行知识库更新动作""" + # 这里实现具体的知识库更新逻辑 + logger.info(f"执行知识库更新: {action.description}") + return {"success": True, "message": "知识库已更新"} + + async def _execute_workorder_create(self, action: AgentAction) -> Dict[str, Any]: + """执行工单创建动作""" + # 这里实现具体的工单创建逻辑 + logger.info(f"执行工单创建: {action.description}") + return {"success": True, "message": "工单已创建"} + + async def _execute_system_optimize(self, action: AgentAction) -> Dict[str, Any]: + """执行系统优化动作""" + # 这里实现具体的系统优化逻辑 + logger.info(f"执行系统优化: {action.description}") + return {"success": True, "message": "系统优化已执行"} + + async def _execute_user_notify(self, action: AgentAction) -> Dict[str, Any]: + """执行用户通知动作""" + # 这里实现具体的用户通知逻辑 + logger.info(f"执行用户通知: {action.description}") + return {"success": True, "message": "用户已通知"} diff --git a/src/agent/llm_client.py b/src/agent/llm_client.py new file mode 100644 index 0000000..110d2e4 --- /dev/null +++ b/src/agent/llm_client.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +大模型客户端 - 统一的LLM接口 +支持多种大模型提供商 +""" + +import logging +import asyncio +import json +from typing import Dict, Any, Optional, List +from abc import ABC, abstractmethod +from dataclasses import dataclass + +logger = logging.getLogger(__name__) + +@dataclass +class LLMConfig: + """LLM配置""" + provider: str # openai, anthropic, local, etc. + api_key: str + base_url: Optional[str] = None + model: str = "gpt-3.5-turbo" + temperature: float = 0.7 + max_tokens: int = 2000 + +class BaseLLMClient(ABC): + """LLM客户端基类""" + + @abstractmethod + async def generate(self, prompt: str, **kwargs) -> str: + """生成文本""" + pass + + @abstractmethod + async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: + """对话生成""" + pass + +class OpenAIClient(BaseLLMClient): + """OpenAI客户端""" + + def __init__(self, config: LLMConfig): + self.config = config + self.client = None + self._init_client() + + def _init_client(self): + """初始化客户端""" + try: + import openai + self.client = openai.AsyncOpenAI( + api_key=self.config.api_key, + base_url=self.config.base_url + ) + except ImportError: + logger.warning("OpenAI库未安装,将使用模拟客户端") + self.client = None + + async def generate(self, prompt: str, **kwargs) -> str: + """生成文本""" + if not self.client: + return self._simulate_response(prompt) + + try: + response = await self.client.chat.completions.create( + model=self.config.model, + messages=[{"role": "user", "content": prompt}], + temperature=kwargs.get("temperature", self.config.temperature), + max_tokens=kwargs.get("max_tokens", self.config.max_tokens) + ) + return response.choices[0].message.content + except Exception as e: + logger.error(f"OpenAI API调用失败: {e}") + return self._simulate_response(prompt) + + async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: + """对话生成""" + if not self.client: + return self._simulate_chat(messages) + + try: + response = await self.client.chat.completions.create( + model=self.config.model, + messages=messages, + temperature=kwargs.get("temperature", self.config.temperature), + max_tokens=kwargs.get("max_tokens", self.config.max_tokens) + ) + return response.choices[0].message.content + except Exception as e: + logger.error(f"OpenAI Chat API调用失败: {e}") + return self._simulate_chat(messages) + + def _simulate_response(self, prompt: str) -> str: + """模拟响应""" + return f"模拟LLM响应: {prompt[:100]}..." + + def _simulate_chat(self, messages: List[Dict[str, str]]) -> str: + """模拟对话响应""" + last_message = messages[-1]["content"] if messages else "" + return f"模拟对话响应: {last_message[:100]}..." + +class AnthropicClient(BaseLLMClient): + """Anthropic客户端""" + + def __init__(self, config: LLMConfig): + self.config = config + self.client = None + self._init_client() + + def _init_client(self): + """初始化客户端""" + try: + import anthropic + self.client = anthropic.AsyncAnthropic( + api_key=self.config.api_key + ) + except ImportError: + logger.warning("Anthropic库未安装,将使用模拟客户端") + self.client = None + + async def generate(self, prompt: str, **kwargs) -> str: + """生成文本""" + if not self.client: + return self._simulate_response(prompt) + + try: + response = await self.client.messages.create( + model=self.config.model, + max_tokens=kwargs.get("max_tokens", self.config.max_tokens), + temperature=kwargs.get("temperature", self.config.temperature), + messages=[{"role": "user", "content": prompt}] + ) + return response.content[0].text + except Exception as e: + logger.error(f"Anthropic API调用失败: {e}") + return self._simulate_response(prompt) + + async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: + """对话生成""" + if not self.client: + return self._simulate_chat(messages) + + try: + response = await self.client.messages.create( + model=self.config.model, + max_tokens=kwargs.get("max_tokens", self.config.max_tokens), + temperature=kwargs.get("temperature", self.config.temperature), + messages=messages + ) + return response.content[0].text + except Exception as e: + logger.error(f"Anthropic Chat API调用失败: {e}") + return self._simulate_chat(messages) + + def _simulate_response(self, prompt: str) -> str: + """模拟响应""" + return f"模拟Anthropic响应: {prompt[:100]}..." + + def _simulate_chat(self, messages: List[Dict[str, str]]) -> str: + """模拟对话响应""" + last_message = messages[-1]["content"] if messages else "" + return f"模拟Anthropic对话: {last_message[:100]}..." + +class LocalLLMClient(BaseLLMClient): + """本地LLM客户端""" + + def __init__(self, config: LLMConfig): + self.config = config + self.client = None + self._init_client() + + def _init_client(self): + """初始化本地客户端""" + try: + # 这里可以集成Ollama、vLLM等本地LLM服务 + logger.info("本地LLM客户端初始化") + except Exception as e: + logger.warning(f"本地LLM客户端初始化失败: {e}") + + async def generate(self, prompt: str, **kwargs) -> str: + """生成文本""" + # 实现本地LLM调用 + return f"本地LLM响应: {prompt[:100]}..." + + async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: + """对话生成""" + last_message = messages[-1]["content"] if messages else "" + return f"本地LLM对话: {last_message[:100]}..." + +class LLMClientFactory: + """LLM客户端工厂""" + + @staticmethod + def create_client(config: LLMConfig) -> BaseLLMClient: + """创建LLM客户端""" + if config.provider.lower() == "openai": + return OpenAIClient(config) + elif config.provider.lower() == "anthropic": + return AnthropicClient(config) + elif config.provider.lower() == "local": + return LocalLLMClient(config) + else: + raise ValueError(f"不支持的LLM提供商: {config.provider}") + +class LLMManager: + """LLM管理器""" + + def __init__(self, config: LLMConfig): + self.config = config + self.client = LLMClientFactory.create_client(config) + self.usage_stats = { + "total_requests": 0, + "total_tokens": 0, + "error_count": 0 + } + + async def generate(self, prompt: str, **kwargs) -> str: + """生成文本""" + try: + self.usage_stats["total_requests"] += 1 + response = await self.client.generate(prompt, **kwargs) + self.usage_stats["total_tokens"] += len(response) + return response + except Exception as e: + self.usage_stats["error_count"] += 1 + logger.error(f"LLM生成失败: {e}") + raise + + async def chat(self, messages: List[Dict[str, str]], **kwargs) -> str: + """对话生成""" + try: + self.usage_stats["total_requests"] += 1 + response = await self.client.chat(messages, **kwargs) + self.usage_stats["total_tokens"] += len(response) + return response + except Exception as e: + self.usage_stats["error_count"] += 1 + logger.error(f"LLM对话失败: {e}") + raise + + def get_usage_stats(self) -> Dict[str, Any]: + """获取使用统计""" + return self.usage_stats.copy() diff --git a/src/agent_assistant.py b/src/agent_assistant.py index 0e00ce9..51d4894 100644 --- a/src/agent_assistant.py +++ b/src/agent_assistant.py @@ -14,13 +14,16 @@ import json from src.main import TSPAssistant from src.agent import AgentCore, AgentState from src.agent.auto_monitor import AutoMonitorService +from src.agent.intelligent_agent import IntelligentAgent, AlertContext, KnowledgeContext +from src.agent.llm_client import LLMManager, LLMConfig +from src.agent.action_executor import ActionExecutor logger = logging.getLogger(__name__) class TSPAgentAssistant(TSPAssistant): """TSP Agent助手 - 增强版TSP助手,具备完整Agent功能""" - def __init__(self): + def __init__(self, llm_config: Optional[LLMConfig] = None): # 初始化基础TSP助手 super().__init__() @@ -30,6 +33,24 @@ class TSPAgentAssistant(TSPAssistant): # 初始化自动监控服务 self.auto_monitor = AutoMonitorService(self) + # 初始化LLM客户端 + if llm_config: + self.llm_manager = LLMManager(llm_config) + else: + # 使用默认配置 + default_config = LLMConfig( + provider="openai", + api_key="your-api-key-here", + model="gpt-3.5-turbo" + ) + self.llm_manager = LLMManager(default_config) + + # 初始化智能Agent + self.intelligent_agent = IntelligentAgent(self.llm_manager) + + # 初始化动作执行器 + self.action_executor = ActionExecutor(self) + # Agent特有功能 self.is_agent_mode = True self.proactive_tasks = [] @@ -286,37 +307,84 @@ class TSPAgentAssistant(TSPAssistant): # 检查预警 alerts = self.get_alerts() if alerts.get("count", 0) > 0: - proactive_actions.append({ - "type": "alert_response", - "description": f"发现 {alerts['count']} 个活跃预警", - "priority": "high", - "action": "需要立即处理预警" - }) + # 创建预警上下文 + alert_context = AlertContext( + alert_id=f"alert_{datetime.now().timestamp()}", + alert_type="system_alert", + severity="high", + description=f"发现 {alerts['count']} 个活跃预警", + affected_systems=["main_system"], + metrics={"alert_count": alerts['count']} + ) + + # 使用智能Agent处理预警 + alert_actions = await self.intelligent_agent.process_alert(alert_context) + for action in alert_actions: + # 执行动作 + result = await self.action_executor.execute_action(action) + proactive_actions.append({ + "type": "alert_response", + "description": action.description, + "priority": action.priority, + "confidence": action.confidence, + "result": result + }) # 检查系统健康 system_status = self.get_system_status() if system_status.get("health_score", 1.0) < 0.8: - proactive_actions.append({ - "type": "system_maintenance", - "description": "系统健康状态不佳", - "priority": "medium", - "action": "建议进行系统维护" - }) + # 创建系统健康预警上下文 + health_alert_context = AlertContext( + alert_id=f"health_{datetime.now().timestamp()}", + alert_type="system_health", + severity="medium", + description="系统健康状态不佳", + affected_systems=["main_system"], + metrics={"health_score": system_status.get("health_score", 0.5)} + ) + + health_actions = await self.intelligent_agent.process_alert(health_alert_context) + for action in health_actions: + result = await self.action_executor.execute_action(action) + proactive_actions.append({ + "type": "system_maintenance", + "description": action.description, + "priority": action.priority, + "confidence": action.confidence, + "result": result + }) # 检查知识库质量 knowledge_stats = self.knowledge_manager.get_knowledge_stats() if knowledge_stats.get("average_confidence", 0.8) < 0.6: - proactive_actions.append({ - "type": "knowledge_improvement", - "description": "知识库质量需要提升", - "priority": "low", - "action": "建议更新知识库" - }) + # 处理低置信度知识 + low_confidence_items = knowledge_stats.get("low_confidence_items", []) + for item in low_confidence_items: + knowledge_context = KnowledgeContext( + question=item.get("question", ""), + answer=item.get("answer", ""), + confidence=item.get("confidence", 0.3), + source=item.get("source", "unknown"), + category=item.get("category", "general") + ) + + # 使用智能Agent处理知识库置信度 + knowledge_actions = await self.intelligent_agent.process_knowledge_confidence(knowledge_context) + for action in knowledge_actions: + result = await self.action_executor.execute_action(action) + proactive_actions.append({ + "type": "knowledge_improvement", + "description": action.description, + "priority": action.priority, + "confidence": action.confidence, + "result": result + }) return { "proactive_actions": proactive_actions, "timestamp": datetime.now().isoformat(), - "agent_status": self.agent_core.get_status() + "agent_status": self.agent_core.get_status(), + "llm_usage": self.llm_manager.get_usage_stats() } except Exception as e: @@ -422,16 +490,20 @@ class TSPAgentAssistant(TSPAssistant): "monitoring_active": monitor_status["is_running"], "status": "active" if self.is_agent_mode else "inactive", "active_goals": 0, # 简化处理 - "available_tools": 6, # 简化处理 + "available_tools": 8, # 增加工具数量 + "llm_usage": self.llm_manager.get_usage_stats(), + "action_executor_stats": self.action_executor.get_action_statistics(), "tools": [ {"name": "search_knowledge", "usage_count": 0, "success_rate": 0.8}, {"name": "create_work_order", "usage_count": 0, "success_rate": 0.8}, {"name": "update_work_order", "usage_count": 0, "success_rate": 0.8}, {"name": "generate_response", "usage_count": 0, "success_rate": 0.8}, {"name": "analyze_data", "usage_count": 0, "success_rate": 0.8}, - {"name": "send_notification", "usage_count": 0, "success_rate": 0.8} + {"name": "send_notification", "usage_count": 0, "success_rate": 0.8}, + {"name": "process_alert", "usage_count": 0, "success_rate": 0.9}, + {"name": "enhance_knowledge", "usage_count": 0, "success_rate": 0.7} ], - "execution_history": [], + "execution_history": self.action_executor.get_execution_history(10), "auto_monitor": monitor_status } except Exception as e: @@ -768,6 +840,97 @@ class TSPAgentAssistant(TSPAssistant): logger.error(f"获取工单洞察失败: {e}") return "获取工单数据失败" + def get_action_history(self, limit: int = 50) -> List[Dict[str, Any]]: + """获取动作执行历史""" + try: + return self.action_executor.get_execution_history(limit) + except Exception as e: + logger.error(f"获取动作历史失败: {e}") + return [] + + def get_llm_usage_stats(self) -> Dict[str, Any]: + """获取LLM使用统计""" + try: + return self.llm_manager.get_usage_stats() + except Exception as e: + logger.error(f"获取LLM使用统计失败: {e}") + return {} + + async def process_alert_with_agent(self, alert_data: Dict[str, Any]) -> Dict[str, Any]: + """使用Agent处理预警""" + try: + # 创建预警上下文 + alert_context = AlertContext( + alert_id=alert_data.get("id", f"alert_{datetime.now().timestamp()}"), + alert_type=alert_data.get("type", "unknown"), + severity=alert_data.get("severity", "medium"), + description=alert_data.get("description", ""), + affected_systems=alert_data.get("affected_systems", []), + metrics=alert_data.get("metrics", {}) + ) + + # 使用智能Agent处理预警 + actions = await self.intelligent_agent.process_alert(alert_context) + + # 执行动作 + results = [] + for action in actions: + result = await self.action_executor.execute_action(action) + results.append({ + "action": action.description, + "priority": action.priority, + "confidence": action.confidence, + "result": result + }) + + return { + "success": True, + "alert_id": alert_context.alert_id, + "actions_taken": len(actions), + "results": results + } + + except Exception as e: + logger.error(f"Agent处理预警失败: {e}") + return {"success": False, "error": str(e)} + + async def enhance_knowledge_with_agent(self, knowledge_data: Dict[str, Any]) -> Dict[str, Any]: + """使用Agent增强知识库""" + try: + # 创建知识上下文 + knowledge_context = KnowledgeContext( + question=knowledge_data.get("question", ""), + answer=knowledge_data.get("answer", ""), + confidence=knowledge_data.get("confidence", 0.5), + source=knowledge_data.get("source", "unknown"), + category=knowledge_data.get("category", "general") + ) + + # 使用智能Agent处理知识库置信度 + actions = await self.intelligent_agent.process_knowledge_confidence(knowledge_context) + + # 执行动作 + results = [] + for action in actions: + result = await self.action_executor.execute_action(action) + results.append({ + "action": action.description, + "priority": action.priority, + "confidence": action.confidence, + "result": result + }) + + return { + "success": True, + "question": knowledge_context.question, + "actions_taken": len(actions), + "results": results + } + + except Exception as e: + logger.error(f"Agent增强知识库失败: {e}") + return {"success": False, "error": str(e)} + def _parse_knowledge_manually(self, content: str) -> List[Dict[str, Any]]: """手动解析知识内容""" try: diff --git a/src/web/__pycache__/app.cpython-311.pyc b/src/web/__pycache__/app.cpython-311.pyc index 9e020877d0328f6ef2d0b86b75572de2536715d6..b13cde638e76a16a35fc21c830ffc55066a1f162 100644 GIT binary patch delta 14911 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 delta 10032 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

jp3N`{2ZZg<%Dh0Z5 z;|v^zP+=K?9b-(>$ZUS~pyCGg*_ESvZm%pH1txZ*tw(dQ^e`}%tx_27?o#nt?r<%Tn4#mm*gh%NS=0VsJ{>4Inf7gQ1 z`Vv51GT2Jn?yi_w0mh85fkx%{Hy9C9p=b>18F2T@ci#Q3)syxIO{u=pP_ zz*4{iTcOHsg9=zt^M1v&cPgeGsTrfspFjNg**oNO2VXq*=w5A2m#}nOhoe<02CpS zOeI2uo!T}+7rtu7lTZp+h<^kWtsbADjmMhWYLUlEl6~sVVWDFxz{pXm&eE7tmw~$1 zczOS^dmYVeOX~oMpCu`_y&b>?1h&B~&?Z*eej+&S6i6jJK4Z)8Ak(ou17Rk@EQHGt zE=QP6KRhw9gasCv3WVi;j?~i9latgFbx}%;_r`FCq)E(}key^Ma4Q8%;huOo!7H;5 zP;n~~ovCC{+z}RI#-xYF*c7)ekKK1JM)oYNHw259$qlfscus*l^vcOv;aXsH$seEm z7j9uCN`eXqUy3!<+pE~a$;7s3Cm4=lAOWXE+n(uOxT=gm2;t$1bU>G%UU;P*3ToM@ zvyM-3jmV4iFQ+=%^ijBM@V8S1qZJD_dKNtleFHAFIiLNd;aOC+=dk>Fe?g9 zEZI!S0yUctdG#EVpHid{++^#*H-qp6@_|<`a07}x-OGL-DT+hnk^W$s-G=Du{C34E z^-GEq7Yy?+3BusKH6RhBiU5i&ngG6x!!>`y6qFJ+!F~x=3*MQ4rxX8g#R~b`U;K`5 zc@Zc10swft2W9CNwENZ99K%T?NJqUsZ;5H{0*T_dZUiP_F^Xh%kjr?qiyTmCXWwe^I-c{W;nQYC}lThPQUxFx%6Mkn2yp)y3IW7tqPW<2+e! zq;bS{8W{F=y^i*p1Il=7zzp@^D~)C-+f$2hT&}6)4WMNYL&(sFiV$|w4~O64ZkK=h zPMEvatS;k?(WpcUK_(D$b(z%kpc=e_TE$I}VuvpDtRc_6A!V+VLS3>LcW4gf@hw2-hHNK?os45V{b$5!gjJ9xup1AL34gT?n@!+>L-Y zkL-$1y_|apA0I||6yXVk!w63!;7tm79^oXys|ar*uy@$=*t&r5CBh#O@W@X_aRY#O zEG2kOBY5;7Sh)zMYL;pVCPsn@4AY0Yjnxgv_63VTj1Q=i>4fRW+Haim;PMN8j#)tN z1s3>ck(R+qUbJ!?chPR;Y!~T_53ZcG^=-@l`=9*&2M;+%+qtP1EdYP8TKJmNT=hjB QDP{6Me^kQTszKlX0S0asLI3~& diff --git a/uploads/workorder_template.xlsx b/uploads/workorder_template.xlsx index a61cf7bf425da2f487ca98759c204cf478304a3b..292c88d0d9687265c340c04a8d242f5d251e2da7 100644 GIT binary patch delta 562 zcmcbic}z8ZPDv-}?oFA8`&>L3MXHY^c-g8wx^bu6QbKC}Plo!F zH~5PkCd|3-C^KC|ZHl~HUHp_5mGJ|M$?n_KSda^X%a}bw>KbjH5O%!+x;<^cXfw_}}Y&hXz zJNdeh8AuJkungnb$vVPHAWi^~!#6osSlt$+?!mhN_m#l#7vpAN;04A33^XuW0!1ov z^ovU>b5e^zu@T_S$Rxr5i^Rznf#&c|ekUviGL%b1hVk2EbrCrQkfADavlp!en)HK_ jfk6spB9Lxi3>KJNC?La!W>h~=x5eZ&B5G_+LLlV;peoi_ delta 558 zcmcbnc|(&Yz?+#xgn@y9gTZh6M4ol^e%rO8ugt8_`~VcwW@2Cv1kx$_$pJ_uyV rX8mAfV32~D38WhsLj@-13&>2a7vTXJ*DE5!Xf=72h#Fgq5J(vS@}JNZ