feat: 重大功能更新 v1.4.0 - 飞书集成、AI语义相似度、前端优化
主要更新内容: - 🚀 飞书多维表格集成,支持工单数据同步 - 🤖 AI建议与人工描述语义相似度计算 - 🎨 前端UI全面优化,现代化设计 - 📊 智能知识库入库策略(AI准确率<90%使用人工描述) - 🔧 代码重构,模块化架构优化 - 📚 完整文档整合和更新 - 🐛 修复配置导入和数据库字段问题 技术特性: - 使用sentence-transformers进行语义相似度计算 - 快速模式结合TF-IDF和语义方法 - 响应式设计,支持移动端 - 加载状态和动画效果 - 配置化AI准确率阈值
This commit is contained in:
18
README.md
18
README.md
@@ -14,6 +14,7 @@
|
||||
- **智能规划**: 基于目标驱动的任务规划和执行
|
||||
- **自主学习**: 从用户反馈中持续优化响应质量
|
||||
- **实时监控**: 主动监控系统状态和异常情况
|
||||
- **模块化重构**: 代码优化,降低运行风险,提升维护性
|
||||
|
||||
### 💬 智能对话系统
|
||||
- **实时通信**: WebSocket支持,毫秒级响应
|
||||
@@ -32,6 +33,7 @@
|
||||
- **版本控制**: 完整的版本管理和变更日志
|
||||
- **热更新**: 支持前端文件热更新,无需重启服务
|
||||
- **自动备份**: 更新前自动备份,支持一键回滚
|
||||
- **飞书集成**: 支持飞书多维表格数据同步和管理
|
||||
|
||||
## 🏗️ 系统架构
|
||||
|
||||
@@ -85,6 +87,13 @@
|
||||
- **端口配置**: Web服务和WebSocket端口管理
|
||||
- **日志级别**: 灵活的日志级别控制
|
||||
|
||||
### 7. 飞书集成 📱
|
||||
- **多维表格同步**: 自动同步飞书多维表格数据
|
||||
- **字段映射**: 智能映射飞书字段到本地数据库
|
||||
- **实时更新**: 支持增量同步和全量同步
|
||||
- **数据预览**: 同步前预览数据,确保准确性
|
||||
- **统一管理**: 飞书功能集成到主仪表板
|
||||
|
||||
## 🛠️ 技术栈
|
||||
|
||||
### 后端技术
|
||||
@@ -260,6 +269,7 @@ LOG_LEVEL=INFO
|
||||
|
||||
### 配置文件
|
||||
- `config/llm_config.py`: LLM客户端配置
|
||||
- `config/integrations_config.json`: 飞书集成配置
|
||||
- `update_config.json`: 更新管理器配置
|
||||
- `version.json`: 版本信息配置
|
||||
|
||||
@@ -280,6 +290,14 @@ LOG_LEVEL=INFO
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.4.0 (2025-09-19)
|
||||
- ✅ 飞书集成功能:支持飞书多维表格数据同步
|
||||
- ✅ 页面功能合并:飞书同步页面合并到主仪表板
|
||||
- ✅ 数据库架构优化:扩展工单表字段,支持飞书数据
|
||||
- ✅ 代码重构优化:大文件拆分,降低运行风险
|
||||
- ✅ 字段映射完善:智能映射飞书字段到本地数据库
|
||||
- ✅ 数据库初始化改进:集成字段迁移到初始化流程
|
||||
|
||||
### v1.3.0 (2025-09-17)
|
||||
- ✅ 数据库架构优化:MySQL主数据库+SQLite备份系统
|
||||
- ✅ 工单详情API修复:解决数据库会话管理问题
|
||||
|
||||
524
TSP智能助手完整文档.md
Normal file
524
TSP智能助手完整文档.md
Normal file
@@ -0,0 +1,524 @@
|
||||
# TSP智能助手完整文档
|
||||
|
||||
## 📋 目录
|
||||
- [项目概述](#项目概述)
|
||||
- [系统架构](#系统架构)
|
||||
- [核心功能](#核心功能)
|
||||
- [技术栈](#技术栈)
|
||||
- [安装部署](#安装部署)
|
||||
- [配置说明](#配置说明)
|
||||
- [使用指南](#使用指南)
|
||||
- [API接口](#api接口)
|
||||
- [数据库设计](#数据库设计)
|
||||
- [开发指南](#开发指南)
|
||||
- [故障排除](#故障排除)
|
||||
- [更新日志](#更新日志)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 项目概述
|
||||
|
||||
TSP智能助手是一个基于大语言模型的智能客服系统,专为TSP(Telematics Service Provider)车辆服务提供商设计。系统集成了智能对话、工单管理、知识库、数据分析、飞书集成等核心功能。
|
||||
|
||||
### 核心特性
|
||||
- **智能Agent架构**: 多工具集成,智能规划,自主学习
|
||||
- **实时对话系统**: WebSocket支持,上下文理解,VIN识别
|
||||
- **数据驱动分析**: 真实数据统计,可视化展示,系统监控
|
||||
- **企业级管理**: 多环境部署,版本控制,热更新,自动备份
|
||||
- **飞书集成**: 支持飞书多维表格数据同步和管理
|
||||
- **AI准确率优化**: 智能判断AI建议质量,优先使用高质量内容入库
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 系统架构
|
||||
|
||||
### 整体架构
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ 前端界面 │ │ 后端服务 │ │ 数据存储 │
|
||||
│ │ │ │ │ │
|
||||
│ • 仪表板 │◄──►│ • Flask API │◄──►│ • MySQL DB │
|
||||
│ • 智能对话 │ │ • WebSocket │ │ • 知识库 │
|
||||
│ • Agent管理 │ │ • Agent核心 │ │ • 工单系统 │
|
||||
│ • 数据分析 │ │ • LLM集成 │ │ • 车辆数据 │
|
||||
│ • 飞书同步 │ │ • 备份系统 │ │ • SQLite备份 │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
### 模块化设计
|
||||
- **Web层**: Flask蓝图架构,模块化API设计
|
||||
- **业务层**: Agent核心、对话管理、工单处理
|
||||
- **数据层**: MySQL主库 + SQLite备份,ORM映射
|
||||
- **集成层**: 飞书API、LLM服务、监控系统
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心功能
|
||||
|
||||
### 1. 智能对话系统 💬
|
||||
- **多轮对话**: 支持上下文关联的连续对话
|
||||
- **VIN识别**: 自动识别车辆VIN并获取实时数据
|
||||
- **知识库检索**: 基于TF-IDF和余弦相似度的智能检索
|
||||
- **工单创建**: 对话中直接创建和关联工单
|
||||
|
||||
### 2. Agent管理系统 🤖
|
||||
- **工具管理**: 10+内置工具,支持自定义工具注册
|
||||
- **执行监控**: 实时监控Agent任务执行状态
|
||||
- **性能统计**: 工具使用频率和成功率分析
|
||||
- **智能规划**: 基于目标的任务分解和执行
|
||||
|
||||
### 3. 工单管理系统 📋
|
||||
- **AI建议生成**: 基于知识库生成工单处理建议
|
||||
- **人工审核**: 支持人工输入和AI建议对比
|
||||
- **语义相似度**: 使用sentence-transformers进行准确度评估
|
||||
- **智能入库**: AI准确率<90%时优先使用人工描述入库
|
||||
- **知识库更新**: 高相似度建议自动入库
|
||||
|
||||
### 4. 知识库管理 📚
|
||||
- **多格式支持**: TXT、PDF、DOC、DOCX、MD文件
|
||||
- **智能提取**: 自动从文档中提取Q&A对
|
||||
- **向量化检索**: TF-IDF + 余弦相似度搜索
|
||||
- **质量验证**: 支持知识条目验证和置信度设置
|
||||
|
||||
### 5. 数据分析系统 📊
|
||||
- **实时趋势**: 基于真实数据的性能趋势分析
|
||||
- **多维度统计**: 工单、预警、满意度等关键指标
|
||||
- **系统健康**: CPU、内存、响应时间监控
|
||||
- **可视化展示**: 丰富的图表和仪表板
|
||||
|
||||
### 6. 飞书集成系统 📱
|
||||
- **多维表格同步**: 自动同步飞书多维表格数据
|
||||
- **字段映射**: 智能映射飞书字段到本地数据库
|
||||
- **实时更新**: 支持增量同步和全量同步
|
||||
- **数据预览**: 同步前预览数据,确保准确性
|
||||
|
||||
### 7. 系统设置管理 ⚙️
|
||||
- **API管理**: 支持多种LLM提供商配置
|
||||
- **模型参数**: 温度、最大令牌数等参数调节
|
||||
- **端口配置**: Web服务和WebSocket端口管理
|
||||
- **日志级别**: 灵活的日志级别控制
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 技术栈
|
||||
|
||||
### 后端技术
|
||||
- **Python 3.8+**: 核心开发语言
|
||||
- **Flask**: Web框架和API服务
|
||||
- **SQLAlchemy**: ORM数据库操作
|
||||
- **WebSocket**: 实时通信支持
|
||||
- **psutil**: 系统资源监控
|
||||
|
||||
### 前端技术
|
||||
- **Bootstrap 5**: UI框架
|
||||
- **Chart.js**: 数据可视化
|
||||
- **JavaScript ES6+**: 前端逻辑
|
||||
- **WebSocket**: 实时通信客户端
|
||||
|
||||
### AI/ML技术
|
||||
- **大语言模型**: 支持OpenAI、通义千问等
|
||||
- **sentence-transformers**: 语义相似度计算
|
||||
- **TF-IDF**: 文本向量化
|
||||
- **余弦相似度**: 语义相似度计算
|
||||
- **Agent框架**: 智能任务规划
|
||||
|
||||
### 部署运维
|
||||
- **Docker**: 容器化部署
|
||||
- **Nginx**: 反向代理和静态文件服务
|
||||
- **Systemd**: 服务管理
|
||||
- **Git**: 版本控制
|
||||
|
||||
---
|
||||
|
||||
## 🚀 安装部署
|
||||
|
||||
### 环境要求
|
||||
- Python 3.8+
|
||||
- Node.js 16+ (可选,用于前端构建)
|
||||
- Git
|
||||
- MySQL 8.0+
|
||||
|
||||
### 安装步骤
|
||||
|
||||
1. **克隆项目**
|
||||
```bash
|
||||
git clone http://jeason.online:3000/zhaojie/assist.git
|
||||
cd assist
|
||||
```
|
||||
|
||||
2. **安装依赖**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **配置数据库**
|
||||
```bash
|
||||
# 创建MySQL数据库
|
||||
mysql -u root -p
|
||||
CREATE DATABASE tsp_assistant CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
4. **初始化数据库**
|
||||
```bash
|
||||
python init_database.py
|
||||
```
|
||||
|
||||
5. **启动服务**
|
||||
```bash
|
||||
python start_dashboard.py
|
||||
```
|
||||
|
||||
6. **访问系统**
|
||||
- 打开浏览器访问: `http://localhost:5000`
|
||||
- 默认端口: 5000 (可在系统设置中修改)
|
||||
|
||||
### Windows快速启动
|
||||
```cmd
|
||||
# 双击运行
|
||||
快速启动.bat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### 环境变量
|
||||
```bash
|
||||
# 数据库配置
|
||||
DATABASE_URL=mysql+pymysql://user:password@host:port/database
|
||||
|
||||
# LLM配置
|
||||
LLM_PROVIDER=openai
|
||||
LLM_API_KEY=your_api_key
|
||||
LLM_MODEL=gpt-3.5-turbo
|
||||
|
||||
# 服务配置
|
||||
SERVER_PORT=5000
|
||||
WEBSOCKET_PORT=8765
|
||||
LOG_LEVEL=INFO
|
||||
```
|
||||
|
||||
### 配置文件结构
|
||||
```
|
||||
config/
|
||||
├── llm_config.py # LLM客户端配置
|
||||
├── integrations_config.json # 飞书集成配置
|
||||
├── ai_accuracy_config.py # AI准确率配置
|
||||
└── README.md # 配置说明文档
|
||||
```
|
||||
|
||||
### 飞书集成配置
|
||||
```json
|
||||
{
|
||||
"feishu": {
|
||||
"app_id": "cli_a8b50ec0eed1500d",
|
||||
"app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK",
|
||||
"app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg",
|
||||
"table_id": "tblnl3vJPpgMTSiP",
|
||||
"status": "active"
|
||||
},
|
||||
"system": {
|
||||
"sync_limit": 10,
|
||||
"ai_suggestions_enabled": true,
|
||||
"auto_sync_interval": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AI准确率配置
|
||||
```python
|
||||
# 默认配置
|
||||
auto_approve_threshold = 0.95 # 自动审批阈值
|
||||
use_human_resolution_threshold = 0.90 # 使用人工描述阈值
|
||||
manual_review_threshold = 0.80 # 人工审核阈值
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📖 使用指南
|
||||
|
||||
### 基础操作
|
||||
|
||||
#### 1. 智能对话
|
||||
1. 在"智能对话"页面输入问题
|
||||
2. 系统自动检索知识库并生成回答
|
||||
3. 支持VIN码识别和车辆数据查询
|
||||
|
||||
#### 2. 工单管理
|
||||
1. 创建工单并获取AI建议
|
||||
2. 输入人工处理描述
|
||||
3. 系统自动计算语义相似度
|
||||
4. 根据相似度决定入库策略
|
||||
|
||||
#### 3. 知识库维护
|
||||
1. 手动添加Q&A对
|
||||
2. 上传文档自动提取知识
|
||||
3. 设置置信度和验证状态
|
||||
|
||||
#### 4. 飞书数据同步
|
||||
1. 配置飞书应用凭证
|
||||
2. 在主仪表板"飞书同步"标签页
|
||||
3. 测试连接并执行数据同步
|
||||
|
||||
### 高级功能
|
||||
|
||||
#### 1. Agent工具管理
|
||||
- 查看工具使用统计
|
||||
- 注册自定义工具
|
||||
- 监控执行历史
|
||||
|
||||
#### 2. 数据分析
|
||||
- 多维度数据统计
|
||||
- 自定义时间范围
|
||||
- 导出分析报告
|
||||
|
||||
#### 3. 系统配置
|
||||
- API和模型参数配置
|
||||
- 端口和日志级别设置
|
||||
- 环境变量管理
|
||||
|
||||
---
|
||||
|
||||
## 🔌 API接口
|
||||
|
||||
### 工单管理API
|
||||
```http
|
||||
POST /api/workorders/{id}/ai-suggestion
|
||||
POST /api/workorders/{id}/human-resolution
|
||||
POST /api/workorders/{id}/approve-to-knowledge
|
||||
GET /api/workorders
|
||||
POST /api/workorders
|
||||
PUT /api/workorders/{id}
|
||||
DELETE /api/workorders/{id}
|
||||
```
|
||||
|
||||
### 知识库API
|
||||
```http
|
||||
GET /api/knowledge
|
||||
POST /api/knowledge
|
||||
PUT /api/knowledge/{id}
|
||||
DELETE /api/knowledge/{id}
|
||||
POST /api/knowledge/search
|
||||
POST /api/knowledge/upload
|
||||
```
|
||||
|
||||
### 对话API
|
||||
```http
|
||||
POST /api/chat/session
|
||||
GET /api/chat/session/{id}
|
||||
DELETE /api/chat/session/{id}
|
||||
POST /api/chat/message
|
||||
```
|
||||
|
||||
### Agent管理API
|
||||
```http
|
||||
GET /api/agent/status
|
||||
POST /api/agent/tools/execute
|
||||
POST /api/agent/tools/register
|
||||
GET /api/agent/tools/stats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ 数据库设计
|
||||
|
||||
### 核心表结构
|
||||
|
||||
#### work_orders (工单表)
|
||||
```sql
|
||||
CREATE TABLE work_orders (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
order_id VARCHAR(50) UNIQUE NOT NULL,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
category VARCHAR(100) NOT NULL,
|
||||
priority VARCHAR(20) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
resolution TEXT,
|
||||
satisfaction_score FLOAT,
|
||||
|
||||
-- 飞书集成字段
|
||||
feishu_record_id VARCHAR(100),
|
||||
source VARCHAR(50),
|
||||
module VARCHAR(100),
|
||||
created_by VARCHAR(100),
|
||||
wilfulness VARCHAR(100),
|
||||
date_of_close DATETIME,
|
||||
vehicle_type VARCHAR(100),
|
||||
vin_sim VARCHAR(50),
|
||||
app_remote_control_version VARCHAR(100),
|
||||
hmi_sw VARCHAR(100),
|
||||
parent_record VARCHAR(100),
|
||||
has_updated_same_day VARCHAR(50),
|
||||
operating_time VARCHAR(100)
|
||||
);
|
||||
```
|
||||
|
||||
#### work_order_suggestions (工单建议表)
|
||||
```sql
|
||||
CREATE TABLE work_order_suggestions (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
work_order_id INT NOT NULL,
|
||||
ai_suggestion TEXT,
|
||||
human_resolution TEXT,
|
||||
ai_similarity FLOAT,
|
||||
approved BOOLEAN DEFAULT FALSE,
|
||||
use_human_resolution BOOLEAN DEFAULT FALSE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (work_order_id) REFERENCES work_orders(id)
|
||||
);
|
||||
```
|
||||
|
||||
#### knowledge_entries (知识库表)
|
||||
```sql
|
||||
CREATE TABLE knowledge_entries (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
question TEXT NOT NULL,
|
||||
answer TEXT NOT NULL,
|
||||
category VARCHAR(100),
|
||||
confidence_score FLOAT DEFAULT 0.5,
|
||||
usage_count INT DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
is_verified BOOLEAN DEFAULT FALSE,
|
||||
verified_by VARCHAR(100),
|
||||
verified_at DATETIME,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 👨💻 开发指南
|
||||
|
||||
### 项目结构
|
||||
```
|
||||
tsp-assistant/
|
||||
├── src/ # 源代码
|
||||
│ ├── agent/ # Agent核心模块
|
||||
│ ├── analytics/ # 数据分析模块
|
||||
│ ├── config/ # 配置模块
|
||||
│ ├── core/ # 核心模块
|
||||
│ ├── dialogue/ # 对话模块
|
||||
│ ├── integrations/ # 集成模块
|
||||
│ ├── knowledge_base/ # 知识库模块
|
||||
│ ├── utils/ # 工具模块
|
||||
│ ├── vehicle/ # 车辆数据模块
|
||||
│ └── web/ # Web应用模块
|
||||
├── config/ # 配置文件
|
||||
├── scripts/ # 脚本文件
|
||||
├── uploads/ # 上传文件
|
||||
├── requirements.txt # 依赖文件
|
||||
├── init_database.py # 数据库初始化
|
||||
└── start_dashboard.py # 启动脚本
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
- **Python**: 遵循PEP 8规范
|
||||
- **JavaScript**: 使用ES6+语法
|
||||
- **提交信息**: 使用约定式提交格式
|
||||
- **文档**: 新功能需要添加相应的文档
|
||||
|
||||
### 开发流程
|
||||
1. Fork项目到个人仓库
|
||||
2. 创建功能分支: `git checkout -b feature/new-feature`
|
||||
3. 提交更改: `git commit -m "Add new feature"`
|
||||
4. 推送分支: `git push origin feature/new-feature`
|
||||
5. 创建Pull Request
|
||||
|
||||
---
|
||||
|
||||
## 🚨 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 1. 数据库连接失败
|
||||
```bash
|
||||
# 检查数据库服务状态
|
||||
systemctl status mysql
|
||||
|
||||
# 检查连接配置
|
||||
python -c "from src.core.database import db_manager; print(db_manager.test_connection())"
|
||||
```
|
||||
|
||||
#### 2. 飞书集成问题
|
||||
- 检查飞书应用权限配置
|
||||
- 验证app_token和table_id是否正确
|
||||
- 确认网络连接和API访问权限
|
||||
|
||||
#### 3. AI建议生成失败
|
||||
- 检查LLM API配置
|
||||
- 验证知识库数据完整性
|
||||
- 查看应用日志
|
||||
|
||||
#### 4. 数据库字段缺失
|
||||
```bash
|
||||
# 运行数据库迁移
|
||||
python init_database.py
|
||||
|
||||
# 手动添加字段
|
||||
mysql -u root -p tsp_assistant
|
||||
ALTER TABLE work_order_suggestions ADD COLUMN use_human_resolution BOOLEAN DEFAULT FALSE;
|
||||
```
|
||||
|
||||
### 日志位置
|
||||
- **应用日志**: `logs/tsp_assistant.log`
|
||||
- **访问日志**: Nginx访问日志
|
||||
- **错误追踪**: 详细的错误堆栈信息
|
||||
|
||||
### 性能优化
|
||||
- **数据库索引**: 为常用查询字段添加索引
|
||||
- **缓存策略**: 使用Redis缓存热点数据
|
||||
- **异步处理**: 耗时操作使用异步处理
|
||||
- **连接池**: 配置数据库连接池
|
||||
|
||||
---
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.4.0 (2025-09-19)
|
||||
- ✅ 飞书集成功能:支持飞书多维表格数据同步
|
||||
- ✅ 页面功能合并:飞书同步页面合并到主仪表板
|
||||
- ✅ 数据库架构优化:扩展工单表字段,支持飞书数据
|
||||
- ✅ 代码重构优化:大文件拆分,降低运行风险
|
||||
- ✅ 字段映射完善:智能映射飞书字段到本地数据库
|
||||
- ✅ 数据库初始化改进:集成字段迁移到初始化流程
|
||||
- ✅ AI准确率优化:AI准确率<90%时优先使用人工描述入库
|
||||
- ✅ 语义相似度计算:使用sentence-transformers提升准确度
|
||||
|
||||
### v1.3.0 (2025-09-17)
|
||||
- ✅ 数据库架构优化:MySQL主数据库+SQLite备份系统
|
||||
- ✅ 工单详情API修复:解决数据库会话管理问题
|
||||
- ✅ 备份管理系统:自动备份MySQL数据到SQLite
|
||||
- ✅ 数据库状态监控:实时监控MySQL和SQLite状态
|
||||
- ✅ 备份管理API:支持数据备份和恢复操作
|
||||
|
||||
### v1.2.0 (2025-09-16)
|
||||
- ✅ 系统设置扩展:API管理、模型参数配置、端口管理
|
||||
- ✅ 真实数据分析:修复性能趋势图表显示问题
|
||||
- ✅ 工单AI建议功能:智能生成处理建议
|
||||
- ✅ 知识库搜索优化:提升检索准确率
|
||||
- ✅ Agent管理改进:工具使用统计和自定义工具
|
||||
|
||||
---
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
|
||||
|
||||
## 📞 支持与联系
|
||||
|
||||
- **项目地址**: http://jeason.online:3000/zhaojie/assist
|
||||
- **问题反馈**: 请在Issues中提交问题
|
||||
- **功能建议**: 欢迎提交Feature Request
|
||||
|
||||
## 🙏 致谢
|
||||
|
||||
感谢所有为项目做出贡献的开发者和用户!
|
||||
|
||||
---
|
||||
|
||||
**TSP智能助手** - 让车辆服务更智能,让客户体验更美好! 🚗✨
|
||||
141
config/README.md
141
config/README.md
@@ -1,16 +1,22 @@
|
||||
# LLM配置说明
|
||||
# TSP智能助手配置说明
|
||||
|
||||
## 千问模型配置
|
||||
## 📋 配置文件概述
|
||||
|
||||
本目录包含TSP智能助手的核心配置文件,包括LLM配置、集成配置等。
|
||||
|
||||
## 🤖 LLM配置
|
||||
|
||||
### 千问模型配置
|
||||
|
||||
本项目默认使用阿里云千问模型。要使用千问模型,请按以下步骤配置:
|
||||
|
||||
### 1. 获取API密钥
|
||||
#### 1. 获取API密钥
|
||||
|
||||
1. 访问 [阿里云百炼平台](https://bailian.console.aliyun.com/)
|
||||
2. 注册并登录账号
|
||||
3. 创建应用并获取API密钥
|
||||
|
||||
### 2. 配置API密钥
|
||||
#### 2. 配置API密钥
|
||||
|
||||
编辑 `config/llm_config.py` 文件,将 `api_key` 替换为您的实际API密钥:
|
||||
|
||||
@@ -25,13 +31,13 @@ QWEN_CONFIG = LLMConfig(
|
||||
)
|
||||
```
|
||||
|
||||
### 3. 可用的千问模型
|
||||
#### 3. 可用的千问模型
|
||||
|
||||
- `qwen-turbo`: 快速响应,适合一般对话
|
||||
- `qwen-plus`: 平衡性能和成本
|
||||
- `qwen-max`: 最强性能,适合复杂任务
|
||||
|
||||
### 4. 环境变量配置(可选)
|
||||
#### 4. 环境变量配置(可选)
|
||||
|
||||
您也可以使用环境变量来配置:
|
||||
|
||||
@@ -40,7 +46,7 @@ export QWEN_API_KEY="sk-your-actual-qwen-api-key"
|
||||
export QWEN_MODEL="qwen-turbo"
|
||||
```
|
||||
|
||||
### 5. 其他模型支持
|
||||
#### 5. 其他模型支持
|
||||
|
||||
项目也支持其他LLM提供商:
|
||||
|
||||
@@ -48,6 +54,125 @@ export QWEN_MODEL="qwen-turbo"
|
||||
- **Anthropic**: Claude系列
|
||||
- **本地模型**: Ollama等
|
||||
|
||||
### 6. 配置验证
|
||||
#### 6. 配置验证
|
||||
|
||||
启动系统后,可以在Agent管理页面查看LLM使用统计,确认配置是否正确。
|
||||
|
||||
## 📱 飞书集成配置
|
||||
|
||||
### 配置文件说明
|
||||
|
||||
`integrations_config.json` 文件包含飞书集成的所有配置信息:
|
||||
|
||||
```json
|
||||
{
|
||||
"feishu": {
|
||||
"app_id": "cli_a8b50ec0eed1500d",
|
||||
"app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK",
|
||||
"app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg",
|
||||
"table_id": "tblnl3vJPpgMTSiP",
|
||||
"last_updated": "2025-09-19T18:27:40.579958",
|
||||
"status": "active"
|
||||
},
|
||||
"system": {
|
||||
"sync_limit": 10,
|
||||
"ai_suggestions_enabled": true,
|
||||
"auto_sync_interval": 0,
|
||||
"last_sync_time": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 配置参数说明
|
||||
|
||||
#### 飞书应用配置
|
||||
- `app_id`: 飞书应用ID
|
||||
- `app_secret`: 飞书应用密钥
|
||||
- `app_token`: 飞书多维表格应用Token
|
||||
- `table_id`: 飞书多维表格ID
|
||||
- `last_updated`: 最后更新时间
|
||||
- `status`: 集成状态(active/inactive)
|
||||
|
||||
#### 系统配置
|
||||
- `sync_limit`: 同步记录数量限制
|
||||
- `ai_suggestions_enabled`: 是否启用AI建议
|
||||
- `auto_sync_interval`: 自动同步间隔(分钟)
|
||||
- `last_sync_time`: 最后同步时间
|
||||
|
||||
### 获取飞书配置
|
||||
|
||||
1. **获取应用凭证**
|
||||
- 访问 [飞书开放平台](https://open.feishu.cn/)
|
||||
- 创建企业自建应用
|
||||
- 获取 `app_id` 和 `app_secret`
|
||||
|
||||
2. **获取表格信息**
|
||||
- 打开飞书多维表格
|
||||
- 从URL中提取 `app_token` 和 `table_id`
|
||||
- 例如:`https://my-ichery.feishu.cn/base/XXnEbiCmEaMblSs6FDJcFCqsnIg?table=tblnl3vJPpgMTSiP`
|
||||
- `app_token`: `XXnEbiCmEaMblSs6FDJcFCqsnIg`
|
||||
- `table_id`: `tblnl3vJPpgMTSiP`
|
||||
|
||||
3. **配置权限**
|
||||
- 在飞书开放平台中配置应用权限
|
||||
- 确保应用有读取多维表格的权限
|
||||
|
||||
### 字段映射配置
|
||||
|
||||
系统会自动映射以下飞书字段到本地数据库:
|
||||
|
||||
| 飞书字段 | 本地字段 | 类型 | 说明 |
|
||||
|---------|---------|------|------|
|
||||
| TR Number | order_id | String | 工单编号 |
|
||||
| TR Description | description | Text | 工单描述 |
|
||||
| Type of problem | category | String | 问题类型 |
|
||||
| TR Level | priority | String | 优先级 |
|
||||
| TR Status | status | String | 工单状态 |
|
||||
| Source | source | String | 来源 |
|
||||
| Created by | created_by | String | 创建人 |
|
||||
| Module(模块) | module | String | 模块 |
|
||||
| Wilfulness(责任人) | wilfulness | String | 责任人 |
|
||||
| Date of close TR | date_of_close | DateTime | 关闭日期 |
|
||||
| Vehicle Type01 | vehicle_type | String | 车型 |
|
||||
| VIN\|sim | vin_sim | String | 车架号/SIM |
|
||||
| App remote control version | app_remote_control_version | String | 应用远程控制版本 |
|
||||
| HMI SW | hmi_sw | String | HMI软件版本 |
|
||||
| 父记录 | parent_record | String | 父记录 |
|
||||
| Has it been updated on the same day | has_updated_same_day | String | 是否同日更新 |
|
||||
| Operating time | operating_time | String | 操作时间 |
|
||||
|
||||
## 🔧 配置管理
|
||||
|
||||
### 配置文件位置
|
||||
- `llm_config.py`: LLM客户端配置
|
||||
- `integrations_config.json`: 集成服务配置
|
||||
- `integrations_config copy.json`: 配置备份文件
|
||||
|
||||
### 配置更新
|
||||
- 修改配置文件后需要重启服务
|
||||
- 建议在修改前备份配置文件
|
||||
- 可以通过Web界面进行部分配置的在线修改
|
||||
|
||||
### 环境变量支持
|
||||
系统支持通过环境变量覆盖配置文件设置:
|
||||
|
||||
```bash
|
||||
# LLM配置
|
||||
export LLM_PROVIDER="openai"
|
||||
export LLM_API_KEY="your-api-key"
|
||||
export LLM_MODEL="gpt-3.5-turbo"
|
||||
|
||||
# 飞书配置
|
||||
export FEISHU_APP_ID="your-app-id"
|
||||
export FEISHU_APP_SECRET="your-app-secret"
|
||||
export FEISHU_APP_TOKEN="your-app-token"
|
||||
export FEISHU_TABLE_ID="your-table-id"
|
||||
```
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
1. **安全性**: 配置文件包含敏感信息,请勿提交到版本控制系统
|
||||
2. **备份**: 修改配置前请备份原文件
|
||||
3. **权限**: 确保飞书应用有足够的权限访问多维表格
|
||||
4. **测试**: 配置完成后建议先进行测试同步
|
||||
5. **监控**: 定期检查同步状态和错误日志
|
||||
|
||||
110
config/ai_accuracy_config.py
Normal file
110
config/ai_accuracy_config.py
Normal file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
AI准确率配置
|
||||
管理AI建议的准确率阈值和相关配置
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, Any
|
||||
|
||||
@dataclass
|
||||
class AIAccuracyConfig:
|
||||
"""AI准确率配置类"""
|
||||
|
||||
# 相似度阈值配置
|
||||
auto_approve_threshold: float = 0.95 # 自动审批阈值(≥95%)
|
||||
use_human_resolution_threshold: float = 0.90 # 使用人工描述阈值(<90%)
|
||||
manual_review_threshold: float = 0.80 # 人工审核阈值(≥80%)
|
||||
|
||||
# 置信度配置
|
||||
ai_suggestion_confidence: float = 0.95 # AI建议默认置信度
|
||||
human_resolution_confidence: float = 0.90 # 人工描述置信度
|
||||
|
||||
# 入库策略配置
|
||||
prefer_human_when_low_accuracy: bool = True # 当AI准确率低时优先使用人工描述
|
||||
enable_auto_approval: bool = True # 是否启用自动审批
|
||||
enable_human_fallback: bool = True # 是否启用人工描述回退
|
||||
|
||||
def get_threshold_explanation(self, similarity: float) -> str:
|
||||
"""获取相似度阈值的解释"""
|
||||
if similarity >= self.auto_approve_threshold:
|
||||
return f"相似度≥{self.auto_approve_threshold*100:.0f}%,自动审批使用AI建议"
|
||||
elif similarity >= self.manual_review_threshold:
|
||||
return f"相似度≥{self.manual_review_threshold*100:.0f}%,建议人工审核"
|
||||
elif similarity >= self.use_human_resolution_threshold:
|
||||
return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,建议使用人工描述"
|
||||
else:
|
||||
return f"相似度<{self.use_human_resolution_threshold*100:.0f}%,优先使用人工描述"
|
||||
|
||||
def should_use_human_resolution(self, similarity: float) -> bool:
|
||||
"""判断是否应该使用人工描述"""
|
||||
return similarity < self.use_human_resolution_threshold
|
||||
|
||||
def should_auto_approve(self, similarity: float) -> bool:
|
||||
"""判断是否应该自动审批"""
|
||||
return similarity >= self.auto_approve_threshold and self.enable_auto_approval
|
||||
|
||||
def get_confidence_score(self, similarity: float, use_human: bool = False) -> float:
|
||||
"""获取置信度分数"""
|
||||
if use_human:
|
||||
return self.human_resolution_confidence
|
||||
else:
|
||||
return max(similarity, self.ai_suggestion_confidence)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""转换为字典格式"""
|
||||
return {
|
||||
"auto_approve_threshold": self.auto_approve_threshold,
|
||||
"use_human_resolution_threshold": self.use_human_resolution_threshold,
|
||||
"manual_review_threshold": self.manual_review_threshold,
|
||||
"ai_suggestion_confidence": self.ai_suggestion_confidence,
|
||||
"human_resolution_confidence": self.human_resolution_confidence,
|
||||
"prefer_human_when_low_accuracy": self.prefer_human_when_low_accuracy,
|
||||
"enable_auto_approval": self.enable_auto_approval,
|
||||
"enable_human_fallback": self.enable_human_fallback
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'AIAccuracyConfig':
|
||||
"""从字典创建配置"""
|
||||
return cls(**data)
|
||||
|
||||
# 默认配置实例
|
||||
DEFAULT_CONFIG = AIAccuracyConfig()
|
||||
|
||||
# 配置预设
|
||||
PRESETS = {
|
||||
"conservative": AIAccuracyConfig(
|
||||
auto_approve_threshold=0.98,
|
||||
use_human_resolution_threshold=0.85,
|
||||
manual_review_threshold=0.90,
|
||||
human_resolution_confidence=0.95
|
||||
),
|
||||
"balanced": AIAccuracyConfig(
|
||||
auto_approve_threshold=0.95,
|
||||
use_human_resolution_threshold=0.90,
|
||||
manual_review_threshold=0.80,
|
||||
human_resolution_confidence=0.90
|
||||
),
|
||||
"aggressive": AIAccuracyConfig(
|
||||
auto_approve_threshold=0.90,
|
||||
use_human_resolution_threshold=0.80,
|
||||
manual_review_threshold=0.70,
|
||||
human_resolution_confidence=0.85
|
||||
)
|
||||
}
|
||||
|
||||
def get_accuracy_config(preset: str = "balanced") -> AIAccuracyConfig:
|
||||
"""获取准确率配置"""
|
||||
return PRESETS.get(preset, DEFAULT_CONFIG)
|
||||
|
||||
def update_accuracy_config(config: AIAccuracyConfig) -> bool:
|
||||
"""更新准确率配置(可以保存到文件或数据库)"""
|
||||
try:
|
||||
# 这里可以实现配置的持久化存储
|
||||
# 例如保存到配置文件或数据库
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"feishu": {
|
||||
"app_id": "tblnl3vJPpgMTSiP",
|
||||
"app_id": "cli_a8b50ec0eed1500d",
|
||||
"app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK",
|
||||
"app_token": "XXnEbiCmEaMblSs6FDJcFCqsnlg",
|
||||
"app_token": "XXnEbiCmEaMblSs6FDJcFCqsnIg",
|
||||
"table_id": "tblnl3vJPpgMTSiP",
|
||||
"last_updated": null,
|
||||
"status": "inactive"
|
||||
"last_updated": "2025-09-19T18:40:55.291113",
|
||||
"status": "active"
|
||||
},
|
||||
"system": {
|
||||
"sync_limit": 10,
|
||||
|
||||
9
database_init_report.json
Normal file
9
database_init_report.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"init_time": "2025-09-19T18:57:01.015501",
|
||||
"database_version": "MySQL 8.4.6",
|
||||
"database_url": "mysql+pymysql://tsp_assistant:***@43.134.68.207/tsp_assistant?charset=utf8mb4",
|
||||
"migrations_applied": 0,
|
||||
"tables_created": 15,
|
||||
"initial_data_inserted": true,
|
||||
"verification_passed": true
|
||||
}
|
||||
836
init_database.py
836
init_database.py
File diff suppressed because it is too large
Load Diff
254
src/agent/agent_assistant_core.py
Normal file
254
src/agent/agent_assistant_core.py
Normal file
@@ -0,0 +1,254 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
TSP Agent助手核心模块
|
||||
包含Agent助手的核心功能和基础类
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
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 TSPAgentAssistantCore(TSPAssistant):
|
||||
"""TSP Agent助手核心 - 基础功能"""
|
||||
|
||||
def __init__(self, llm_config: Optional[LLMConfig] = None):
|
||||
# 初始化基础TSP助手
|
||||
super().__init__()
|
||||
|
||||
# 初始化Agent核心
|
||||
self.agent_core = AgentCore()
|
||||
|
||||
# 初始化自动监控服务
|
||||
self.auto_monitor = AutoMonitorService(self)
|
||||
|
||||
# 初始化LLM客户端
|
||||
self._init_llm_manager(llm_config)
|
||||
|
||||
# 初始化智能Agent
|
||||
self.intelligent_agent = IntelligentAgent(
|
||||
llm_manager=self.llm_manager,
|
||||
agent_core=self.agent_core
|
||||
)
|
||||
|
||||
# 初始化动作执行器
|
||||
self.action_executor = ActionExecutor(self)
|
||||
|
||||
# Agent状态
|
||||
self.agent_state = AgentState.IDLE
|
||||
self.is_agent_mode = True
|
||||
self.proactive_monitoring_enabled = False
|
||||
|
||||
# 执行历史
|
||||
self.execution_history = []
|
||||
self.max_history_size = 1000
|
||||
|
||||
logger.info("TSP Agent助手核心初始化完成")
|
||||
|
||||
def _init_llm_manager(self, llm_config: Optional[LLMConfig] = None):
|
||||
"""初始化LLM管理器"""
|
||||
if llm_config:
|
||||
self.llm_manager = LLMManager(llm_config)
|
||||
else:
|
||||
# 使用默认配置 - 千问模型
|
||||
try:
|
||||
from config.llm_config import DEFAULT_CONFIG
|
||||
self.llm_manager = LLMManager(DEFAULT_CONFIG)
|
||||
except ImportError:
|
||||
# 如果配置文件不存在,使用内置配置
|
||||
default_config = LLMConfig(
|
||||
provider="openai",
|
||||
api_key="sk-your-qwen-api-key-here",
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
model="qwen-turbo",
|
||||
temperature=0.7,
|
||||
max_tokens=2000
|
||||
)
|
||||
self.llm_manager = LLMManager(default_config)
|
||||
|
||||
def get_agent_status(self) -> Dict[str, Any]:
|
||||
"""获取Agent状态"""
|
||||
return {
|
||||
"agent_state": self.agent_state.value,
|
||||
"is_agent_mode": self.is_agent_mode,
|
||||
"proactive_monitoring": self.proactive_monitoring_enabled,
|
||||
"execution_count": len(self.execution_history),
|
||||
"llm_status": self.llm_manager.get_status(),
|
||||
"agent_core_status": self.agent_core.get_status(),
|
||||
"last_activity": self.execution_history[-1]["timestamp"] if self.execution_history else None
|
||||
}
|
||||
|
||||
def toggle_agent_mode(self, enabled: bool) -> bool:
|
||||
"""切换Agent模式"""
|
||||
try:
|
||||
self.is_agent_mode = enabled
|
||||
if enabled:
|
||||
self.agent_state = AgentState.IDLE
|
||||
logger.info("Agent模式已启用")
|
||||
else:
|
||||
self.agent_state = AgentState.DISABLED
|
||||
logger.info("Agent模式已禁用")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"切换Agent模式失败: {e}")
|
||||
return False
|
||||
|
||||
def start_proactive_monitoring(self) -> bool:
|
||||
"""启动主动监控"""
|
||||
try:
|
||||
if not self.proactive_monitoring_enabled:
|
||||
self.proactive_monitoring_enabled = True
|
||||
self.auto_monitor.start_monitoring()
|
||||
logger.info("主动监控已启动")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"启动主动监控失败: {e}")
|
||||
return False
|
||||
|
||||
def stop_proactive_monitoring(self) -> bool:
|
||||
"""停止主动监控"""
|
||||
try:
|
||||
if self.proactive_monitoring_enabled:
|
||||
self.proactive_monitoring_enabled = False
|
||||
self.auto_monitor.stop_monitoring()
|
||||
logger.info("主动监控已停止")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"停止主动监控失败: {e}")
|
||||
return False
|
||||
|
||||
def run_proactive_monitoring(self) -> Dict[str, Any]:
|
||||
"""运行主动监控检查"""
|
||||
try:
|
||||
if not self.proactive_monitoring_enabled:
|
||||
return {"success": False, "message": "主动监控未启用"}
|
||||
|
||||
# 获取系统状态
|
||||
system_health = self.get_system_health()
|
||||
|
||||
# 检查预警
|
||||
alerts = self.check_alerts()
|
||||
|
||||
# 检查工单状态
|
||||
workorders_status = self._check_workorders_status()
|
||||
|
||||
# 运行智能分析
|
||||
analysis = self.intelligent_agent.analyze_system_state(
|
||||
system_health=system_health,
|
||||
alerts=alerts,
|
||||
workorders=workorders_status
|
||||
)
|
||||
|
||||
# 执行建议的动作
|
||||
actions_taken = []
|
||||
if analysis.get("recommended_actions"):
|
||||
for action in analysis["recommended_actions"]:
|
||||
result = self.action_executor.execute_action(action)
|
||||
actions_taken.append(result)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"analysis": analysis,
|
||||
"actions_taken": actions_taken,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"主动监控检查失败: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def _check_workorders_status(self) -> Dict[str, Any]:
|
||||
"""检查工单状态"""
|
||||
try:
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import WorkOrder
|
||||
|
||||
with db_manager.get_session() as session:
|
||||
total_workorders = session.query(WorkOrder).count()
|
||||
open_workorders = session.query(WorkOrder).filter(WorkOrder.status == 'open').count()
|
||||
resolved_workorders = session.query(WorkOrder).filter(WorkOrder.status == 'resolved').count()
|
||||
|
||||
return {
|
||||
"total": total_workorders,
|
||||
"open": open_workorders,
|
||||
"resolved": resolved_workorders,
|
||||
"resolution_rate": resolved_workorders / total_workorders if total_workorders > 0 else 0
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"检查工单状态失败: {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
def run_intelligent_analysis(self) -> Dict[str, Any]:
|
||||
"""运行智能分析"""
|
||||
try:
|
||||
# 获取系统数据
|
||||
system_health = self.get_system_health()
|
||||
alerts = self.check_alerts()
|
||||
workorders = self._check_workorders_status()
|
||||
|
||||
# 创建分析上下文
|
||||
context = {
|
||||
"system_health": system_health,
|
||||
"alerts": alerts,
|
||||
"workorders": workorders,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# 运行智能分析
|
||||
analysis = self.intelligent_agent.comprehensive_analysis(context)
|
||||
|
||||
# 记录分析结果
|
||||
self._record_execution("intelligent_analysis", analysis)
|
||||
|
||||
return analysis
|
||||
except Exception as e:
|
||||
logger.error(f"智能分析失败: {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
def _record_execution(self, action_type: str, result: Any):
|
||||
"""记录执行历史"""
|
||||
execution_record = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"action_type": action_type,
|
||||
"result": result,
|
||||
"agent_state": self.agent_state.value
|
||||
}
|
||||
|
||||
self.execution_history.append(execution_record)
|
||||
|
||||
# 保持历史记录大小限制
|
||||
if len(self.execution_history) > self.max_history_size:
|
||||
self.execution_history = self.execution_history[-self.max_history_size:]
|
||||
|
||||
def get_action_history(self, limit: int = 50) -> List[Dict[str, Any]]:
|
||||
"""获取动作执行历史"""
|
||||
return self.execution_history[-limit:] if self.execution_history else []
|
||||
|
||||
def clear_execution_history(self) -> Dict[str, Any]:
|
||||
"""清空执行历史"""
|
||||
try:
|
||||
self.execution_history.clear()
|
||||
logger.info("执行历史已清空")
|
||||
return {"success": True, "message": "执行历史已清空"}
|
||||
except Exception as e:
|
||||
logger.error(f"清空执行历史失败: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
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 {"error": str(e)}
|
||||
243
src/agent/agent_message_handler.py
Normal file
243
src/agent/agent_message_handler.py
Normal file
@@ -0,0 +1,243 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
TSP Agent消息处理模块
|
||||
处理Agent的消息处理和对话功能
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
from .agent_assistant_core import TSPAgentAssistantCore
|
||||
from .intelligent_agent import IntelligentAgent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AgentMessageHandler:
|
||||
"""Agent消息处理器"""
|
||||
|
||||
def __init__(self, agent_core: TSPAgentAssistantCore):
|
||||
self.agent_core = agent_core
|
||||
self.intelligent_agent = agent_core.intelligent_agent
|
||||
self.action_executor = agent_core.action_executor
|
||||
|
||||
async def process_message_agent(self, message: str, user_id: str = "admin",
|
||||
work_order_id: Optional[int] = None,
|
||||
enable_proactive: bool = True) -> Dict[str, Any]:
|
||||
"""使用Agent处理消息"""
|
||||
try:
|
||||
# 更新Agent状态
|
||||
self.agent_core.agent_state = self.agent_core.agent_core.AgentState.PROCESSING
|
||||
|
||||
# 创建对话上下文
|
||||
context = {
|
||||
"message": message,
|
||||
"user_id": user_id,
|
||||
"work_order_id": work_order_id,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"enable_proactive": enable_proactive
|
||||
}
|
||||
|
||||
# 使用智能Agent处理消息
|
||||
agent_response = await self.intelligent_agent.process_message(context)
|
||||
|
||||
# 执行建议的动作
|
||||
actions_taken = []
|
||||
if agent_response.get("recommended_actions"):
|
||||
for action in agent_response["recommended_actions"]:
|
||||
action_result = self.action_executor.execute_action(action)
|
||||
actions_taken.append(action_result)
|
||||
|
||||
# 生成响应
|
||||
response = {
|
||||
"response": agent_response.get("response", "Agent已处理您的请求"),
|
||||
"actions": actions_taken,
|
||||
"status": "completed",
|
||||
"confidence": agent_response.get("confidence", 0.8),
|
||||
"context": context
|
||||
}
|
||||
|
||||
# 记录执行历史
|
||||
self.agent_core._record_execution("message_processing", response)
|
||||
|
||||
# 更新Agent状态
|
||||
self.agent_core.agent_state = self.agent_core.agent_core.AgentState.IDLE
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Agent消息处理失败: {e}")
|
||||
self.agent_core.agent_state = self.agent_core.agent_core.AgentState.ERROR
|
||||
|
||||
return {
|
||||
"response": f"处理消息时发生错误: {str(e)}",
|
||||
"actions": [],
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def process_conversation_agent(self, conversation_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理对话"""
|
||||
try:
|
||||
# 提取对话信息
|
||||
user_message = conversation_data.get("message", "")
|
||||
user_id = conversation_data.get("user_id", "anonymous")
|
||||
session_id = conversation_data.get("session_id")
|
||||
|
||||
# 创建对话上下文
|
||||
context = {
|
||||
"message": user_message,
|
||||
"user_id": user_id,
|
||||
"session_id": session_id,
|
||||
"conversation_history": conversation_data.get("history", []),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# 使用智能Agent处理对话
|
||||
agent_response = await self.intelligent_agent.process_conversation(context)
|
||||
|
||||
# 执行建议的动作
|
||||
actions_taken = []
|
||||
if agent_response.get("recommended_actions"):
|
||||
for action in agent_response["recommended_actions"]:
|
||||
action_result = self.action_executor.execute_action(action)
|
||||
actions_taken.append(action_result)
|
||||
|
||||
# 生成响应
|
||||
response = {
|
||||
"response": agent_response.get("response", "Agent已处理您的对话"),
|
||||
"actions": actions_taken,
|
||||
"status": "completed",
|
||||
"confidence": agent_response.get("confidence", 0.8),
|
||||
"context": context,
|
||||
"session_id": session_id
|
||||
}
|
||||
|
||||
# 记录执行历史
|
||||
self.agent_core._record_execution("conversation_processing", response)
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Agent对话处理失败: {e}")
|
||||
return {
|
||||
"response": f"处理对话时发生错误: {str(e)}",
|
||||
"actions": [],
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def process_workorder_agent(self, workorder_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理工单"""
|
||||
try:
|
||||
# 提取工单信息
|
||||
workorder_id = workorder_data.get("workorder_id")
|
||||
action_type = workorder_data.get("action_type", "analyze")
|
||||
|
||||
# 创建工单上下文
|
||||
context = {
|
||||
"workorder_id": workorder_id,
|
||||
"action_type": action_type,
|
||||
"workorder_data": workorder_data,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# 使用智能Agent处理工单
|
||||
agent_response = await self.intelligent_agent.process_workorder(context)
|
||||
|
||||
# 执行建议的动作
|
||||
actions_taken = []
|
||||
if agent_response.get("recommended_actions"):
|
||||
for action in agent_response["recommended_actions"]:
|
||||
action_result = self.action_executor.execute_action(action)
|
||||
actions_taken.append(action_result)
|
||||
|
||||
# 生成响应
|
||||
response = {
|
||||
"response": agent_response.get("response", "Agent已处理工单"),
|
||||
"actions": actions_taken,
|
||||
"status": "completed",
|
||||
"confidence": agent_response.get("confidence", 0.8),
|
||||
"context": context
|
||||
}
|
||||
|
||||
# 记录执行历史
|
||||
self.agent_core._record_execution("workorder_processing", response)
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Agent工单处理失败: {e}")
|
||||
return {
|
||||
"response": f"处理工单时发生错误: {str(e)}",
|
||||
"actions": [],
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def process_alert_agent(self, alert_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理预警"""
|
||||
try:
|
||||
# 创建预警上下文
|
||||
context = {
|
||||
"alert_data": alert_data,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# 使用智能Agent处理预警
|
||||
agent_response = await self.intelligent_agent.process_alert(context)
|
||||
|
||||
# 执行建议的动作
|
||||
actions_taken = []
|
||||
if agent_response.get("recommended_actions"):
|
||||
for action in agent_response["recommended_actions"]:
|
||||
action_result = self.action_executor.execute_action(action)
|
||||
actions_taken.append(action_result)
|
||||
|
||||
# 生成响应
|
||||
response = {
|
||||
"response": agent_response.get("response", "Agent已处理预警"),
|
||||
"actions": actions_taken,
|
||||
"status": "completed",
|
||||
"confidence": agent_response.get("confidence", 0.8),
|
||||
"context": context
|
||||
}
|
||||
|
||||
# 记录执行历史
|
||||
self.agent_core._record_execution("alert_processing", response)
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Agent预警处理失败: {e}")
|
||||
return {
|
||||
"response": f"处理预警时发生错误: {str(e)}",
|
||||
"actions": [],
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
def get_conversation_suggestions(self, context: Dict[str, Any]) -> List[str]:
|
||||
"""获取对话建议"""
|
||||
try:
|
||||
return self.intelligent_agent.get_conversation_suggestions(context)
|
||||
except Exception as e:
|
||||
logger.error(f"获取对话建议失败: {e}")
|
||||
return []
|
||||
|
||||
def get_workorder_suggestions(self, workorder_data: Dict[str, Any]) -> List[str]:
|
||||
"""获取工单建议"""
|
||||
try:
|
||||
return self.intelligent_agent.get_workorder_suggestions(workorder_data)
|
||||
except Exception as e:
|
||||
logger.error(f"获取工单建议失败: {e}")
|
||||
return []
|
||||
|
||||
def get_alert_suggestions(self, alert_data: Dict[str, Any]) -> List[str]:
|
||||
"""获取预警建议"""
|
||||
try:
|
||||
return self.intelligent_agent.get_alert_suggestions(alert_data)
|
||||
except Exception as e:
|
||||
logger.error(f"获取预警建议失败: {e}")
|
||||
return []
|
||||
405
src/agent/agent_sample_actions.py
Normal file
405
src/agent/agent_sample_actions.py
Normal file
@@ -0,0 +1,405 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
TSP Agent示例动作模块
|
||||
包含Agent的示例动作和测试功能
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Any, List
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from .agent_assistant_core import TSPAgentAssistantCore
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AgentSampleActions:
|
||||
"""Agent示例动作处理器"""
|
||||
|
||||
def __init__(self, agent_core: TSPAgentAssistantCore):
|
||||
self.agent_core = agent_core
|
||||
|
||||
async def trigger_sample_actions(self) -> Dict[str, Any]:
|
||||
"""触发示例动作"""
|
||||
try:
|
||||
logger.info("开始执行示例动作")
|
||||
|
||||
# 执行多个示例动作
|
||||
actions_results = []
|
||||
|
||||
# 1. 系统健康检查
|
||||
health_result = await self._sample_health_check()
|
||||
actions_results.append(health_result)
|
||||
|
||||
# 2. 预警分析
|
||||
alert_result = await self._sample_alert_analysis()
|
||||
actions_results.append(alert_result)
|
||||
|
||||
# 3. 工单处理
|
||||
workorder_result = await self._sample_workorder_processing()
|
||||
actions_results.append(workorder_result)
|
||||
|
||||
# 4. 知识库更新
|
||||
knowledge_result = await self._sample_knowledge_update()
|
||||
actions_results.append(knowledge_result)
|
||||
|
||||
# 5. 性能优化
|
||||
optimization_result = await self._sample_performance_optimization()
|
||||
actions_results.append(optimization_result)
|
||||
|
||||
# 记录执行历史
|
||||
self.agent_core._record_execution("sample_actions", {
|
||||
"actions_count": len(actions_results),
|
||||
"results": actions_results
|
||||
})
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"成功执行 {len(actions_results)} 个示例动作",
|
||||
"actions_results": actions_results,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"执行示例动作失败: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
async def _sample_health_check(self) -> Dict[str, Any]:
|
||||
"""示例:系统健康检查"""
|
||||
try:
|
||||
# 获取系统健康状态
|
||||
health_data = self.agent_core.get_system_health()
|
||||
|
||||
# 模拟健康检查逻辑
|
||||
health_score = health_data.get("health_score", 0)
|
||||
|
||||
if health_score > 80:
|
||||
status = "excellent"
|
||||
message = "系统运行状态良好"
|
||||
elif health_score > 60:
|
||||
status = "good"
|
||||
message = "系统运行状态正常"
|
||||
elif health_score > 40:
|
||||
status = "fair"
|
||||
message = "系统运行状态一般,建议关注"
|
||||
else:
|
||||
status = "poor"
|
||||
message = "系统运行状态较差,需要优化"
|
||||
|
||||
return {
|
||||
"action_type": "health_check",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"health_score": health_score,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"健康检查失败: {e}")
|
||||
return {
|
||||
"action_type": "health_check",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _sample_alert_analysis(self) -> Dict[str, Any]:
|
||||
"""示例:预警分析"""
|
||||
try:
|
||||
# 获取预警数据
|
||||
alerts = self.agent_core.check_alerts()
|
||||
|
||||
# 分析预警
|
||||
alert_count = len(alerts)
|
||||
critical_alerts = [a for a in alerts if a.get("level") == "critical"]
|
||||
warning_alerts = [a for a in alerts if a.get("level") == "warning"]
|
||||
|
||||
# 生成分析结果
|
||||
if alert_count == 0:
|
||||
status = "no_alerts"
|
||||
message = "当前无活跃预警"
|
||||
elif len(critical_alerts) > 0:
|
||||
status = "critical"
|
||||
message = f"发现 {len(critical_alerts)} 个严重预警,需要立即处理"
|
||||
elif len(warning_alerts) > 0:
|
||||
status = "warning"
|
||||
message = f"发现 {len(warning_alerts)} 个警告预警,建议关注"
|
||||
else:
|
||||
status = "info"
|
||||
message = f"发现 {alert_count} 个信息预警"
|
||||
|
||||
return {
|
||||
"action_type": "alert_analysis",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"alert_count": alert_count,
|
||||
"critical_count": len(critical_alerts),
|
||||
"warning_count": len(warning_alerts),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"预警分析失败: {e}")
|
||||
return {
|
||||
"action_type": "alert_analysis",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _sample_workorder_processing(self) -> Dict[str, Any]:
|
||||
"""示例:工单处理"""
|
||||
try:
|
||||
# 获取工单状态
|
||||
workorders_status = self.agent_core._check_workorders_status()
|
||||
|
||||
total = workorders_status.get("total", 0)
|
||||
open_count = workorders_status.get("open", 0)
|
||||
resolved_count = workorders_status.get("resolved", 0)
|
||||
resolution_rate = workorders_status.get("resolution_rate", 0)
|
||||
|
||||
# 分析工单状态
|
||||
if total == 0:
|
||||
status = "no_workorders"
|
||||
message = "当前无工单"
|
||||
elif open_count > 10:
|
||||
status = "high_backlog"
|
||||
message = f"工单积压严重,有 {open_count} 个待处理工单"
|
||||
elif resolution_rate > 0.8:
|
||||
status = "good_resolution"
|
||||
message = f"工单处理效率良好,解决率 {resolution_rate:.1%}"
|
||||
else:
|
||||
status = "normal"
|
||||
message = f"工单处理状态正常,待处理 {open_count} 个"
|
||||
|
||||
return {
|
||||
"action_type": "workorder_processing",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"total_workorders": total,
|
||||
"open_workorders": open_count,
|
||||
"resolved_workorders": resolved_count,
|
||||
"resolution_rate": resolution_rate,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"工单处理分析失败: {e}")
|
||||
return {
|
||||
"action_type": "workorder_processing",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _sample_knowledge_update(self) -> Dict[str, Any]:
|
||||
"""示例:知识库更新"""
|
||||
try:
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import KnowledgeEntry
|
||||
|
||||
with db_manager.get_session() as session:
|
||||
# 获取知识库统计
|
||||
total_knowledge = session.query(KnowledgeEntry).count()
|
||||
verified_knowledge = session.query(KnowledgeEntry).filter(
|
||||
KnowledgeEntry.is_verified == True
|
||||
).count()
|
||||
unverified_knowledge = total_knowledge - verified_knowledge
|
||||
|
||||
# 分析知识库状态
|
||||
if total_knowledge == 0:
|
||||
status = "empty"
|
||||
message = "知识库为空,建议添加知识条目"
|
||||
elif unverified_knowledge > 0:
|
||||
status = "needs_verification"
|
||||
message = f"有 {unverified_knowledge} 个知识条目需要验证"
|
||||
else:
|
||||
status = "up_to_date"
|
||||
message = "知识库状态良好,所有条目已验证"
|
||||
|
||||
return {
|
||||
"action_type": "knowledge_update",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"total_knowledge": total_knowledge,
|
||||
"verified_knowledge": verified_knowledge,
|
||||
"unverified_knowledge": unverified_knowledge,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"知识库更新分析失败: {e}")
|
||||
return {
|
||||
"action_type": "knowledge_update",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _sample_performance_optimization(self) -> Dict[str, Any]:
|
||||
"""示例:性能优化"""
|
||||
try:
|
||||
# 获取系统性能数据
|
||||
system_health = self.agent_core.get_system_health()
|
||||
|
||||
# 分析性能指标
|
||||
cpu_usage = system_health.get("cpu_usage", 0)
|
||||
memory_usage = system_health.get("memory_usage", 0)
|
||||
disk_usage = system_health.get("disk_usage", 0)
|
||||
|
||||
# 生成优化建议
|
||||
optimization_suggestions = []
|
||||
|
||||
if cpu_usage > 80:
|
||||
optimization_suggestions.append("CPU使用率过高,建议优化计算密集型任务")
|
||||
if memory_usage > 80:
|
||||
optimization_suggestions.append("内存使用率过高,建议清理缓存或增加内存")
|
||||
if disk_usage > 90:
|
||||
optimization_suggestions.append("磁盘空间不足,建议清理日志文件或扩容")
|
||||
|
||||
if not optimization_suggestions:
|
||||
status = "optimal"
|
||||
message = "系统性能良好,无需优化"
|
||||
else:
|
||||
status = "needs_optimization"
|
||||
message = f"发现 {len(optimization_suggestions)} 个性能优化点"
|
||||
|
||||
return {
|
||||
"action_type": "performance_optimization",
|
||||
"status": status,
|
||||
"message": message,
|
||||
"cpu_usage": cpu_usage,
|
||||
"memory_usage": memory_usage,
|
||||
"disk_usage": disk_usage,
|
||||
"optimization_suggestions": optimization_suggestions,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"性能优化分析失败: {e}")
|
||||
return {
|
||||
"action_type": "performance_optimization",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def run_performance_test(self) -> Dict[str, Any]:
|
||||
"""运行性能测试"""
|
||||
try:
|
||||
start_time = datetime.now()
|
||||
|
||||
# 执行多个测试
|
||||
test_results = []
|
||||
|
||||
# 1. 响应时间测试
|
||||
response_time = await self._test_response_time()
|
||||
test_results.append(response_time)
|
||||
|
||||
# 2. 并发处理测试
|
||||
concurrency_test = await self._test_concurrency()
|
||||
test_results.append(concurrency_test)
|
||||
|
||||
# 3. 内存使用测试
|
||||
memory_test = await self._test_memory_usage()
|
||||
test_results.append(memory_test)
|
||||
|
||||
end_time = datetime.now()
|
||||
total_time = (end_time - start_time).total_seconds()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "性能测试完成",
|
||||
"total_time": total_time,
|
||||
"test_results": test_results,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"性能测试失败: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
async def _test_response_time(self) -> Dict[str, Any]:
|
||||
"""测试响应时间"""
|
||||
start_time = datetime.now()
|
||||
|
||||
# 模拟处理任务
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
end_time = datetime.now()
|
||||
response_time = (end_time - start_time).total_seconds()
|
||||
|
||||
return {
|
||||
"test_type": "response_time",
|
||||
"response_time": response_time,
|
||||
"status": "good" if response_time < 0.5 else "slow"
|
||||
}
|
||||
|
||||
async def _test_concurrency(self) -> Dict[str, Any]:
|
||||
"""测试并发处理"""
|
||||
try:
|
||||
# 创建多个并发任务
|
||||
tasks = []
|
||||
for i in range(5):
|
||||
task = asyncio.create_task(self._simulate_task(i))
|
||||
tasks.append(task)
|
||||
|
||||
# 等待所有任务完成
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
||||
return {
|
||||
"test_type": "concurrency",
|
||||
"concurrent_tasks": len(tasks),
|
||||
"successful_tasks": len([r for r in results if r.get("success")]),
|
||||
"status": "good"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"test_type": "concurrency",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _simulate_task(self, task_id: int) -> Dict[str, Any]:
|
||||
"""模拟任务"""
|
||||
try:
|
||||
await asyncio.sleep(0.05) # 模拟处理时间
|
||||
return {
|
||||
"task_id": task_id,
|
||||
"success": True,
|
||||
"result": f"Task {task_id} completed"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"task_id": task_id,
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
async def _test_memory_usage(self) -> Dict[str, Any]:
|
||||
"""测试内存使用"""
|
||||
try:
|
||||
import psutil
|
||||
|
||||
# 获取当前内存使用情况
|
||||
memory_info = psutil.virtual_memory()
|
||||
|
||||
return {
|
||||
"test_type": "memory_usage",
|
||||
"total_memory": memory_info.total,
|
||||
"available_memory": memory_info.available,
|
||||
"used_memory": memory_info.used,
|
||||
"memory_percentage": memory_info.percent,
|
||||
"status": "good" if memory_info.percent < 80 else "high"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"test_type": "memory_usage",
|
||||
"status": "error",
|
||||
"error": str(e)
|
||||
}
|
||||
@@ -2,72 +2,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
增强版TSP助手 - 集成Agent功能
|
||||
这是一个真正的智能Agent实现
|
||||
重构版本:模块化设计,降低代码复杂度
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
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
|
||||
from src.agent.agent_assistant_core import TSPAgentAssistantCore
|
||||
from src.agent.agent_message_handler import AgentMessageHandler
|
||||
from src.agent.agent_sample_actions import AgentSampleActions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TSPAgentAssistant(TSPAssistant):
|
||||
"""TSP Agent助手 - 增强版TSP助手,具备完整Agent功能"""
|
||||
class TSPAgentAssistant(TSPAgentAssistantCore):
|
||||
"""TSP Agent助手 - 重构版本"""
|
||||
|
||||
def __init__(self, llm_config: Optional[LLMConfig] = None):
|
||||
# 初始化基础TSP助手
|
||||
super().__init__()
|
||||
def __init__(self, llm_config=None):
|
||||
# 初始化核心功能
|
||||
super().__init__(llm_config)
|
||||
|
||||
# 初始化Agent核心
|
||||
self.agent_core = AgentCore()
|
||||
# 初始化消息处理器
|
||||
self.message_handler = AgentMessageHandler(self)
|
||||
|
||||
# 初始化自动监控服务
|
||||
self.auto_monitor = AutoMonitorService(self)
|
||||
# 初始化示例动作处理器
|
||||
self.sample_actions = AgentSampleActions(self)
|
||||
|
||||
# 初始化LLM客户端
|
||||
if llm_config:
|
||||
self.llm_manager = LLMManager(llm_config)
|
||||
else:
|
||||
# 使用默认配置 - 千问模型
|
||||
try:
|
||||
from config.llm_config import DEFAULT_CONFIG
|
||||
self.llm_manager = LLMManager(DEFAULT_CONFIG)
|
||||
except ImportError:
|
||||
# 如果配置文件不存在,使用内置配置
|
||||
default_config = LLMConfig(
|
||||
provider="openai",
|
||||
api_key="sk-your-qwen-api-key-here",
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||
model="qwen-turbo",
|
||||
temperature=0.7,
|
||||
max_tokens=2000
|
||||
)
|
||||
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 = []
|
||||
self.agent_memory = {}
|
||||
|
||||
# 添加一些示例执行历史(用于演示)
|
||||
self._add_sample_execution_history()
|
||||
|
||||
logger.info("TSP Agent助手初始化完成")
|
||||
logger.info("TSP Agent助手初始化完成(重构版本)")
|
||||
|
||||
async def process_message_agent(
|
||||
self,
|
||||
|
||||
322
src/agent_assistant_new.py
Normal file
322
src/agent_assistant_new.py
Normal file
@@ -0,0 +1,322 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
增强版TSP助手 - 集成Agent功能
|
||||
重构版本:模块化设计,降低代码复杂度
|
||||
"""
|
||||
|
||||
import logging
|
||||
import asyncio
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
from src.agent.agent_assistant_core import TSPAgentAssistantCore
|
||||
from src.agent.agent_message_handler import AgentMessageHandler
|
||||
from src.agent.agent_sample_actions import AgentSampleActions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TSPAgentAssistant(TSPAgentAssistantCore):
|
||||
"""TSP Agent助手 - 重构版本"""
|
||||
|
||||
def __init__(self, llm_config=None):
|
||||
# 初始化核心功能
|
||||
super().__init__(llm_config)
|
||||
|
||||
# 初始化消息处理器
|
||||
self.message_handler = AgentMessageHandler(self)
|
||||
|
||||
# 初始化示例动作处理器
|
||||
self.sample_actions = AgentSampleActions(self)
|
||||
|
||||
logger.info("TSP Agent助手初始化完成(重构版本)")
|
||||
|
||||
# ==================== 消息处理功能 ====================
|
||||
|
||||
async def process_message_agent(self, message: str, user_id: str = "admin",
|
||||
work_order_id: Optional[int] = None,
|
||||
enable_proactive: bool = True) -> Dict[str, Any]:
|
||||
"""使用Agent处理消息"""
|
||||
return await self.message_handler.process_message_agent(
|
||||
message, user_id, work_order_id, enable_proactive
|
||||
)
|
||||
|
||||
async def process_conversation_agent(self, conversation_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理对话"""
|
||||
return await self.message_handler.process_conversation_agent(conversation_data)
|
||||
|
||||
async def process_workorder_agent(self, workorder_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理工单"""
|
||||
return await self.message_handler.process_workorder_agent(workorder_data)
|
||||
|
||||
async def process_alert_agent(self, alert_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""使用Agent处理预警"""
|
||||
return await self.message_handler.process_alert_agent(alert_data)
|
||||
|
||||
# ==================== 建议功能 ====================
|
||||
|
||||
def get_conversation_suggestions(self, context: Dict[str, Any]) -> List[str]:
|
||||
"""获取对话建议"""
|
||||
return self.message_handler.get_conversation_suggestions(context)
|
||||
|
||||
def get_workorder_suggestions(self, workorder_data: Dict[str, Any]) -> List[str]:
|
||||
"""获取工单建议"""
|
||||
return self.message_handler.get_workorder_suggestions(workorder_data)
|
||||
|
||||
def get_alert_suggestions(self, alert_data: Dict[str, Any]) -> List[str]:
|
||||
"""获取预警建议"""
|
||||
return self.message_handler.get_alert_suggestions(alert_data)
|
||||
|
||||
# ==================== 示例动作功能 ====================
|
||||
|
||||
async def trigger_sample_actions(self) -> Dict[str, Any]:
|
||||
"""触发示例动作"""
|
||||
return await self.sample_actions.trigger_sample_actions()
|
||||
|
||||
async def run_performance_test(self) -> Dict[str, Any]:
|
||||
"""运行性能测试"""
|
||||
return await self.sample_actions.run_performance_test()
|
||||
|
||||
# ==================== 兼容性方法 ====================
|
||||
|
||||
def get_agent_status(self) -> Dict[str, Any]:
|
||||
"""获取Agent状态(兼容性方法)"""
|
||||
return super().get_agent_status()
|
||||
|
||||
def toggle_agent_mode(self, enabled: bool) -> bool:
|
||||
"""切换Agent模式(兼容性方法)"""
|
||||
return super().toggle_agent_mode(enabled)
|
||||
|
||||
def start_proactive_monitoring(self) -> bool:
|
||||
"""启动主动监控(兼容性方法)"""
|
||||
return super().start_proactive_monitoring()
|
||||
|
||||
def stop_proactive_monitoring(self) -> bool:
|
||||
"""停止主动监控(兼容性方法)"""
|
||||
return super().stop_proactive_monitoring()
|
||||
|
||||
def run_proactive_monitoring(self) -> Dict[str, Any]:
|
||||
"""运行主动监控检查(兼容性方法)"""
|
||||
return super().run_proactive_monitoring()
|
||||
|
||||
def run_intelligent_analysis(self) -> Dict[str, Any]:
|
||||
"""运行智能分析(兼容性方法)"""
|
||||
return super().run_intelligent_analysis()
|
||||
|
||||
def get_action_history(self, limit: int = 50) -> List[Dict[str, Any]]:
|
||||
"""获取动作执行历史(兼容性方法)"""
|
||||
return super().get_action_history(limit)
|
||||
|
||||
def clear_execution_history(self) -> Dict[str, Any]:
|
||||
"""清空执行历史(兼容性方法)"""
|
||||
return super().clear_execution_history()
|
||||
|
||||
def get_llm_usage_stats(self) -> Dict[str, Any]:
|
||||
"""获取LLM使用统计(兼容性方法)"""
|
||||
return super().get_llm_usage_stats()
|
||||
|
||||
# ==================== 高级功能 ====================
|
||||
|
||||
async def comprehensive_analysis(self) -> Dict[str, Any]:
|
||||
"""综合分析 - 结合多个模块的分析结果"""
|
||||
try:
|
||||
# 运行智能分析
|
||||
intelligent_analysis = self.run_intelligent_analysis()
|
||||
|
||||
# 运行主动监控
|
||||
proactive_monitoring = self.run_proactive_monitoring()
|
||||
|
||||
# 运行性能测试
|
||||
performance_test = await self.run_performance_test()
|
||||
|
||||
# 综合结果
|
||||
comprehensive_result = {
|
||||
"timestamp": self.execution_history[-1]["timestamp"] if self.execution_history else None,
|
||||
"intelligent_analysis": intelligent_analysis,
|
||||
"proactive_monitoring": proactive_monitoring,
|
||||
"performance_test": performance_test,
|
||||
"overall_status": self._determine_overall_status(
|
||||
intelligent_analysis, proactive_monitoring, performance_test
|
||||
)
|
||||
}
|
||||
|
||||
# 记录综合分析
|
||||
self._record_execution("comprehensive_analysis", comprehensive_result)
|
||||
|
||||
return comprehensive_result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"综合分析失败: {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
def _determine_overall_status(self, intelligent_analysis: Dict,
|
||||
proactive_monitoring: Dict,
|
||||
performance_test: Dict) -> str:
|
||||
"""确定整体状态"""
|
||||
try:
|
||||
# 检查各个模块的状态
|
||||
statuses = []
|
||||
|
||||
if intelligent_analysis.get("success"):
|
||||
statuses.append("intelligent_analysis_ok")
|
||||
else:
|
||||
statuses.append("intelligent_analysis_error")
|
||||
|
||||
if proactive_monitoring.get("success"):
|
||||
statuses.append("proactive_monitoring_ok")
|
||||
else:
|
||||
statuses.append("proactive_monitoring_error")
|
||||
|
||||
if performance_test.get("success"):
|
||||
statuses.append("performance_test_ok")
|
||||
else:
|
||||
statuses.append("performance_test_error")
|
||||
|
||||
# 根据状态确定整体状态
|
||||
if all("ok" in status for status in statuses):
|
||||
return "excellent"
|
||||
elif any("error" in status for status in statuses):
|
||||
return "needs_attention"
|
||||
else:
|
||||
return "good"
|
||||
|
||||
except Exception:
|
||||
return "unknown"
|
||||
|
||||
async def batch_process_requests(self, requests: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||
"""批量处理请求"""
|
||||
try:
|
||||
results = []
|
||||
|
||||
for request in requests:
|
||||
request_type = request.get("type", "message")
|
||||
|
||||
if request_type == "message":
|
||||
result = await self.process_message_agent(
|
||||
request.get("message", ""),
|
||||
request.get("user_id", "admin"),
|
||||
request.get("work_order_id"),
|
||||
request.get("enable_proactive", True)
|
||||
)
|
||||
elif request_type == "conversation":
|
||||
result = await self.process_conversation_agent(request)
|
||||
elif request_type == "workorder":
|
||||
result = await self.process_workorder_agent(request)
|
||||
elif request_type == "alert":
|
||||
result = await self.process_alert_agent(request)
|
||||
else:
|
||||
result = {"error": f"未知请求类型: {request_type}"}
|
||||
|
||||
results.append(result)
|
||||
|
||||
# 记录批量处理
|
||||
self._record_execution("batch_process", {
|
||||
"request_count": len(requests),
|
||||
"results": results
|
||||
})
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"批量处理请求失败: {e}")
|
||||
return [{"error": str(e)} for _ in requests]
|
||||
|
||||
def get_system_summary(self) -> Dict[str, Any]:
|
||||
"""获取系统摘要"""
|
||||
try:
|
||||
# 获取各种状态信息
|
||||
agent_status = self.get_agent_status()
|
||||
system_health = self.get_system_health()
|
||||
workorders_status = self._check_workorders_status()
|
||||
|
||||
# 计算摘要指标
|
||||
summary = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"agent_status": agent_status,
|
||||
"system_health": system_health,
|
||||
"workorders_status": workorders_status,
|
||||
"execution_history_count": len(self.execution_history),
|
||||
"llm_usage_stats": self.get_llm_usage_stats(),
|
||||
"overall_health_score": system_health.get("health_score", 0)
|
||||
}
|
||||
|
||||
return summary
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取系统摘要失败: {e}")
|
||||
return {"error": str(e)}
|
||||
|
||||
def export_agent_data(self) -> Dict[str, Any]:
|
||||
"""导出Agent数据"""
|
||||
try:
|
||||
export_data = {
|
||||
"export_timestamp": datetime.now().isoformat(),
|
||||
"agent_status": self.get_agent_status(),
|
||||
"execution_history": self.execution_history,
|
||||
"llm_usage_stats": self.get_llm_usage_stats(),
|
||||
"system_summary": self.get_system_summary()
|
||||
}
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"data": export_data,
|
||||
"message": "Agent数据导出成功"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"导出Agent数据失败: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
def import_agent_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""导入Agent数据"""
|
||||
try:
|
||||
# 验证数据格式
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError("数据格式不正确")
|
||||
|
||||
# 导入执行历史
|
||||
if "execution_history" in data:
|
||||
self.execution_history = data["execution_history"]
|
||||
|
||||
# 其他数据的导入逻辑...
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": "Agent数据导入成功"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"导入Agent数据失败: {e}")
|
||||
return {
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}
|
||||
|
||||
# 测试函数
|
||||
async def main():
|
||||
"""测试函数"""
|
||||
print("🚀 TSP Agent助手测试")
|
||||
|
||||
# 创建Agent助手实例
|
||||
agent_assistant = TSPAgentAssistant()
|
||||
|
||||
# 测试基本功能
|
||||
status = agent_assistant.get_agent_status()
|
||||
print("Agent状态:", status)
|
||||
|
||||
# 测试消息处理
|
||||
result = await agent_assistant.process_message_agent("你好,请帮我分析系统状态")
|
||||
print("消息处理结果:", result)
|
||||
|
||||
# 测试示例动作
|
||||
sample_result = await agent_assistant.trigger_sample_actions()
|
||||
print("示例动作结果:", sample_result)
|
||||
|
||||
# 测试综合分析
|
||||
analysis_result = await agent_assistant.comprehensive_analysis()
|
||||
print("综合分析结果:", analysis_result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -10,7 +10,7 @@ class Config:
|
||||
ALIBABA_MODEL_NAME = "qwen-plus-latest"
|
||||
|
||||
# 数据库配置
|
||||
DATABASE_URL = "sqlite:///tsp_assistant.db"
|
||||
DATABASE_URL = "mysql+pymysql://tsp_assistant:123456@43.134.68.207/tsp_assistant?charset=utf8mb4"
|
||||
|
||||
# 知识库配置
|
||||
KNOWLEDGE_BASE_PATH = "data/knowledge_base"
|
||||
|
||||
279
src/config/unified_config.py
Normal file
279
src/config/unified_config.py
Normal file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
统一配置管理模块
|
||||
整合所有配置,提供统一的配置接口
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from dataclasses import dataclass, asdict
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclass
|
||||
class DatabaseConfig:
|
||||
"""数据库配置"""
|
||||
url: str = "mysql+pymysql://tsp_assistant:password@43.134.68.207/tsp_assistant?charset=utf8mb4"
|
||||
pool_size: int = 10
|
||||
max_overflow: int = 20
|
||||
pool_timeout: int = 30
|
||||
pool_recycle: int = 3600
|
||||
|
||||
@dataclass
|
||||
class LLMConfig:
|
||||
"""LLM配置"""
|
||||
provider: str = "openai"
|
||||
api_key: str = ""
|
||||
base_url: str = "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
model: str = "qwen-turbo"
|
||||
temperature: float = 0.7
|
||||
max_tokens: int = 2000
|
||||
timeout: int = 30
|
||||
|
||||
@dataclass
|
||||
class ServerConfig:
|
||||
"""服务器配置"""
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 5000
|
||||
websocket_port: int = 8765
|
||||
debug: bool = False
|
||||
log_level: str = "INFO"
|
||||
|
||||
@dataclass
|
||||
class FeishuConfig:
|
||||
"""飞书配置"""
|
||||
app_id: str = ""
|
||||
app_secret: str = ""
|
||||
app_token: str = ""
|
||||
table_id: str = ""
|
||||
status: str = "active"
|
||||
sync_limit: int = 10
|
||||
auto_sync_interval: int = 0
|
||||
|
||||
@dataclass
|
||||
class AIAccuracyConfig:
|
||||
"""AI准确率配置"""
|
||||
auto_approve_threshold: float = 0.95
|
||||
use_human_resolution_threshold: float = 0.90
|
||||
manual_review_threshold: float = 0.80
|
||||
ai_suggestion_confidence: float = 0.95
|
||||
human_resolution_confidence: float = 0.90
|
||||
prefer_human_when_low_accuracy: bool = True
|
||||
enable_auto_approval: bool = True
|
||||
enable_human_fallback: bool = True
|
||||
|
||||
@dataclass
|
||||
class SystemConfig:
|
||||
"""系统配置"""
|
||||
backup_enabled: bool = True
|
||||
backup_interval: int = 24 # 小时
|
||||
max_backup_files: int = 7
|
||||
cache_enabled: bool = True
|
||||
cache_ttl: int = 3600 # 秒
|
||||
monitoring_enabled: bool = True
|
||||
|
||||
class UnifiedConfig:
|
||||
"""统一配置管理器"""
|
||||
|
||||
def __init__(self, config_dir: str = "config"):
|
||||
self.config_dir = Path(config_dir)
|
||||
self.config_file = self.config_dir / "unified_config.json"
|
||||
|
||||
# 默认配置
|
||||
self.database = DatabaseConfig()
|
||||
self.llm = LLMConfig()
|
||||
self.server = ServerConfig()
|
||||
self.feishu = FeishuConfig()
|
||||
self.ai_accuracy = AIAccuracyConfig()
|
||||
self.system = SystemConfig()
|
||||
|
||||
# 加载配置
|
||||
self.load_config()
|
||||
|
||||
def load_config(self):
|
||||
"""加载配置文件"""
|
||||
try:
|
||||
if self.config_file.exists():
|
||||
with open(self.config_file, 'r', encoding='utf-8') as f:
|
||||
config_data = json.load(f)
|
||||
|
||||
# 更新配置
|
||||
if 'database' in config_data:
|
||||
self.database = DatabaseConfig(**config_data['database'])
|
||||
if 'llm' in config_data:
|
||||
self.llm = LLMConfig(**config_data['llm'])
|
||||
if 'server' in config_data:
|
||||
self.server = ServerConfig(**config_data['server'])
|
||||
if 'feishu' in config_data:
|
||||
self.feishu = FeishuConfig(**config_data['feishu'])
|
||||
if 'ai_accuracy' in config_data:
|
||||
self.ai_accuracy = AIAccuracyConfig(**config_data['ai_accuracy'])
|
||||
if 'system' in config_data:
|
||||
self.system = SystemConfig(**config_data['system'])
|
||||
|
||||
logger.info("配置文件加载成功")
|
||||
else:
|
||||
logger.info("配置文件不存在,使用默认配置")
|
||||
self.save_config()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"加载配置文件失败: {e}")
|
||||
|
||||
def save_config(self):
|
||||
"""保存配置文件"""
|
||||
try:
|
||||
self.config_dir.mkdir(exist_ok=True)
|
||||
|
||||
config_data = {
|
||||
'database': asdict(self.database),
|
||||
'llm': asdict(self.llm),
|
||||
'server': asdict(self.server),
|
||||
'feishu': asdict(self.feishu),
|
||||
'ai_accuracy': asdict(self.ai_accuracy),
|
||||
'system': asdict(self.system)
|
||||
}
|
||||
|
||||
with open(self.config_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(config_data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
logger.info("配置文件保存成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"保存配置文件失败: {e}")
|
||||
|
||||
def load_from_env(self):
|
||||
"""从环境变量加载配置"""
|
||||
# 数据库配置
|
||||
if os.getenv('DATABASE_URL'):
|
||||
self.database.url = os.getenv('DATABASE_URL')
|
||||
|
||||
# LLM配置
|
||||
if os.getenv('LLM_PROVIDER'):
|
||||
self.llm.provider = os.getenv('LLM_PROVIDER')
|
||||
if os.getenv('LLM_API_KEY'):
|
||||
self.llm.api_key = os.getenv('LLM_API_KEY')
|
||||
if os.getenv('LLM_MODEL'):
|
||||
self.llm.model = os.getenv('LLM_MODEL')
|
||||
|
||||
# 服务器配置
|
||||
if os.getenv('SERVER_PORT'):
|
||||
self.server.port = int(os.getenv('SERVER_PORT'))
|
||||
if os.getenv('LOG_LEVEL'):
|
||||
self.server.log_level = os.getenv('LOG_LEVEL')
|
||||
|
||||
# 飞书配置
|
||||
if os.getenv('FEISHU_APP_ID'):
|
||||
self.feishu.app_id = os.getenv('FEISHU_APP_ID')
|
||||
if os.getenv('FEISHU_APP_SECRET'):
|
||||
self.feishu.app_secret = os.getenv('FEISHU_APP_SECRET')
|
||||
if os.getenv('FEISHU_APP_TOKEN'):
|
||||
self.feishu.app_token = os.getenv('FEISHU_APP_TOKEN')
|
||||
if os.getenv('FEISHU_TABLE_ID'):
|
||||
self.feishu.table_id = os.getenv('FEISHU_TABLE_ID')
|
||||
|
||||
def get_database_url(self) -> str:
|
||||
"""获取数据库连接URL"""
|
||||
return self.database.url
|
||||
|
||||
def get_llm_config(self) -> Dict[str, Any]:
|
||||
"""获取LLM配置"""
|
||||
return asdict(self.llm)
|
||||
|
||||
def get_server_config(self) -> Dict[str, Any]:
|
||||
"""获取服务器配置"""
|
||||
return asdict(self.server)
|
||||
|
||||
def get_feishu_config(self) -> Dict[str, Any]:
|
||||
"""获取飞书配置"""
|
||||
return asdict(self.feishu)
|
||||
|
||||
def get_ai_accuracy_config(self) -> Dict[str, Any]:
|
||||
"""获取AI准确率配置"""
|
||||
return asdict(self.ai_accuracy)
|
||||
|
||||
def get_system_config(self) -> Dict[str, Any]:
|
||||
"""获取系统配置"""
|
||||
return asdict(self.system)
|
||||
|
||||
def update_config(self, section: str, config_data: Dict[str, Any]):
|
||||
"""更新配置"""
|
||||
try:
|
||||
if section == 'database':
|
||||
self.database = DatabaseConfig(**config_data)
|
||||
elif section == 'llm':
|
||||
self.llm = LLMConfig(**config_data)
|
||||
elif section == 'server':
|
||||
self.server = ServerConfig(**config_data)
|
||||
elif section == 'feishu':
|
||||
self.feishu = FeishuConfig(**config_data)
|
||||
elif section == 'ai_accuracy':
|
||||
self.ai_accuracy = AIAccuracyConfig(**config_data)
|
||||
elif section == 'system':
|
||||
self.system = SystemConfig(**config_data)
|
||||
else:
|
||||
raise ValueError(f"未知的配置节: {section}")
|
||||
|
||||
self.save_config()
|
||||
logger.info(f"配置节 {section} 更新成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"更新配置失败: {e}")
|
||||
raise
|
||||
|
||||
def validate_config(self) -> bool:
|
||||
"""验证配置有效性"""
|
||||
try:
|
||||
# 验证数据库配置
|
||||
if not self.database.url:
|
||||
logger.error("数据库URL未配置")
|
||||
return False
|
||||
|
||||
# 验证LLM配置
|
||||
if not self.llm.api_key:
|
||||
logger.warning("LLM API密钥未配置")
|
||||
|
||||
# 验证飞书配置
|
||||
if self.feishu.status == "active":
|
||||
if not all([self.feishu.app_id, self.feishu.app_secret,
|
||||
self.feishu.app_token, self.feishu.table_id]):
|
||||
logger.warning("飞书配置不完整")
|
||||
|
||||
logger.info("配置验证通过")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"配置验证失败: {e}")
|
||||
return False
|
||||
|
||||
def get_all_config(self) -> Dict[str, Any]:
|
||||
"""获取所有配置"""
|
||||
return {
|
||||
'database': asdict(self.database),
|
||||
'llm': asdict(self.llm),
|
||||
'server': asdict(self.server),
|
||||
'feishu': asdict(self.feishu),
|
||||
'ai_accuracy': asdict(self.ai_accuracy),
|
||||
'system': asdict(self.system)
|
||||
}
|
||||
|
||||
# 全局配置实例
|
||||
_config_instance = None
|
||||
|
||||
def get_config() -> UnifiedConfig:
|
||||
"""获取全局配置实例"""
|
||||
global _config_instance
|
||||
if _config_instance is None:
|
||||
_config_instance = UnifiedConfig()
|
||||
_config_instance.load_from_env()
|
||||
return _config_instance
|
||||
|
||||
def reload_config():
|
||||
"""重新加载配置"""
|
||||
global _config_instance
|
||||
_config_instance = None
|
||||
return get_config()
|
||||
@@ -27,6 +27,20 @@ class WorkOrder(Base):
|
||||
solution = Column(Text, nullable=True) # 解决方案
|
||||
ai_suggestion = Column(Text, nullable=True) # AI建议
|
||||
|
||||
# 扩展飞书字段
|
||||
source = Column(String(50), nullable=True) # 来源(Mail, Telegram bot等)
|
||||
module = Column(String(100), nullable=True) # 模块(local O&M, OTA等)
|
||||
created_by = Column(String(100), nullable=True) # 创建人
|
||||
wilfulness = Column(String(100), nullable=True) # 责任人
|
||||
date_of_close = Column(DateTime, nullable=True) # 关闭日期
|
||||
vehicle_type = Column(String(100), nullable=True) # 车型
|
||||
vin_sim = Column(String(50), nullable=True) # 车架号/SIM
|
||||
app_remote_control_version = Column(String(100), nullable=True) # 应用远程控制版本
|
||||
hmi_sw = Column(String(100), nullable=True) # HMI软件版本
|
||||
parent_record = Column(String(100), nullable=True) # 父记录
|
||||
has_updated_same_day = Column(String(50), nullable=True) # 是否同日更新
|
||||
operating_time = Column(String(100), nullable=True) # 操作时间
|
||||
|
||||
# 关联对话记录
|
||||
conversations = relationship("Conversation", back_populates="work_order")
|
||||
|
||||
@@ -119,5 +133,6 @@ class WorkOrderSuggestion(Base):
|
||||
human_resolution = Column(Text)
|
||||
ai_similarity = Column(Float)
|
||||
approved = Column(Boolean, default=False)
|
||||
use_human_resolution = Column(Boolean, default=False) # 是否使用人工描述入库
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
|
||||
@@ -46,16 +46,31 @@ class WorkOrderSyncService:
|
||||
|
||||
# 字段映射配置 - 根据实际飞书表格结构
|
||||
self.field_mapping = {
|
||||
# 飞书字段名 -> 本地字段名
|
||||
# 核心字段
|
||||
"TR Number": "order_id", # TR编号映射到工单号
|
||||
"TR Description": "title", # TR描述作为标题(问题描述)
|
||||
"TR Description": "description", # TR描述作为详细描述
|
||||
"Type of problem": "category", # 问题类型作为分类
|
||||
"TR Level": "priority", # TR Level作为优先级
|
||||
"TR Status": "status", # TR Status作为状态(修正字段名)
|
||||
"Source": "assignee", # 来源信息
|
||||
"TR Status": "status", # TR Status作为状态
|
||||
"Source": "source", # 来源信息(Mail, Telegram bot等)
|
||||
"Date creation": "created_at", # 创建日期
|
||||
"处理过程": "description", # 处理过程作为描述
|
||||
"TR tracking": "solution", # TR跟踪作为解决方案
|
||||
"处理过程": "solution", # 处理过程作为解决方案
|
||||
"TR tracking": "resolution", # TR跟踪作为解决方案详情
|
||||
|
||||
# 扩展字段
|
||||
"Created by": "created_by", # 创建人
|
||||
"Module(模块)": "module", # 模块
|
||||
"Wilfulness(责任人)": "wilfulness", # 责任人
|
||||
"Date of close TR": "date_of_close", # 关闭日期
|
||||
"Vehicle Type01": "vehicle_type", # 车型
|
||||
"VIN|sim": "vin_sim", # 车架号/SIM
|
||||
"App remote control version": "app_remote_control_version", # 应用远程控制版本
|
||||
"HMI SW": "hmi_sw", # HMI软件版本
|
||||
"父记录": "parent_record", # 父记录
|
||||
"Has it been updated on the same day": "has_updated_same_day", # 是否同日更新
|
||||
"Operating time": "operating_time", # 操作时间
|
||||
|
||||
# AI建议字段
|
||||
"AI建议": "ai_suggestion", # AI建议字段
|
||||
"Issue Start Time": "updated_at" # 问题开始时间作为更新时间
|
||||
}
|
||||
@@ -387,7 +402,7 @@ class WorkOrderSyncService:
|
||||
value = self.status_mapping[value]
|
||||
elif local_field == "priority" and value in self.priority_mapping:
|
||||
value = self.priority_mapping[value]
|
||||
elif local_field in ["created_at", "updated_at"] and value:
|
||||
elif local_field in ["created_at", "updated_at", "date_of_close"] and value:
|
||||
try:
|
||||
# 处理飞书时间戳(毫秒)
|
||||
if isinstance(value, (int, float)):
|
||||
@@ -404,6 +419,16 @@ class WorkOrderSyncService:
|
||||
else:
|
||||
logger.info(f"飞书字段 {feishu_field} 不存在于数据中")
|
||||
|
||||
# 生成标题 - 使用TR Number和问题类型
|
||||
tr_number = feishu_fields.get("TR Number", "")
|
||||
problem_type = feishu_fields.get("Type of problem", "")
|
||||
if tr_number and problem_type:
|
||||
local_data["title"] = f"{tr_number} - {problem_type}"
|
||||
elif tr_number:
|
||||
local_data["title"] = f"{tr_number} - TR工单"
|
||||
else:
|
||||
local_data["title"] = "TR工单"
|
||||
|
||||
# 设置默认值
|
||||
if "status" not in local_data:
|
||||
local_data["status"] = WorkOrderStatus.PENDING
|
||||
@@ -411,8 +436,6 @@ class WorkOrderSyncService:
|
||||
local_data["priority"] = WorkOrderPriority.MEDIUM
|
||||
if "category" not in local_data:
|
||||
local_data["category"] = "Remote control" # 根据表格中最常见的问题类型
|
||||
if "title" not in local_data or not local_data["title"]:
|
||||
local_data["title"] = "TR工单" # 默认标题
|
||||
|
||||
return local_data
|
||||
|
||||
|
||||
@@ -76,18 +76,24 @@ def extract_keywords(text: str, max_keywords: int = 10) -> List[str]:
|
||||
return [word for word, count in sorted_words[:max_keywords]]
|
||||
|
||||
def calculate_similarity(text1: str, text2: str) -> float:
|
||||
"""计算文本相似度"""
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
|
||||
"""计算文本相似度(使用语义相似度)"""
|
||||
try:
|
||||
vectorizer = TfidfVectorizer()
|
||||
vectors = vectorizer.fit_transform([text1, text2])
|
||||
similarity = cosine_similarity(vectors[0:1], vectors[1:2])[0][0]
|
||||
return float(similarity)
|
||||
from src.utils.semantic_similarity import calculate_semantic_similarity
|
||||
return calculate_semantic_similarity(text1, text2)
|
||||
except Exception as e:
|
||||
logging.error(f"计算相似度失败: {e}")
|
||||
return 0.0
|
||||
logging.error(f"计算语义相似度失败: {e}")
|
||||
# 回退到传统方法
|
||||
try:
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
|
||||
vectorizer = TfidfVectorizer()
|
||||
vectors = vectorizer.fit_transform([text1, text2])
|
||||
similarity = cosine_similarity(vectors[0:1], vectors[1:2])[0][0]
|
||||
return float(similarity)
|
||||
except Exception as e2:
|
||||
logging.error(f"计算TF-IDF相似度失败: {e2}")
|
||||
return 0.0
|
||||
|
||||
def format_time_duration(seconds: float) -> str:
|
||||
"""格式化时间持续时间"""
|
||||
|
||||
256
src/utils/semantic_similarity.py
Normal file
256
src/utils/semantic_similarity.py
Normal file
@@ -0,0 +1,256 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
语义相似度计算服务
|
||||
使用sentence-transformers进行更准确的语义相似度计算
|
||||
"""
|
||||
|
||||
import logging
|
||||
import numpy as np
|
||||
from typing import List, Tuple, Optional
|
||||
from sentence_transformers import SentenceTransformer
|
||||
import torch
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class SemanticSimilarityCalculator:
|
||||
"""语义相似度计算器"""
|
||||
|
||||
def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
|
||||
"""
|
||||
初始化语义相似度计算器
|
||||
|
||||
Args:
|
||||
model_name: 使用的预训练模型名称
|
||||
- all-MiniLM-L6-v2: 英文模型,速度快,推荐用于生产环境
|
||||
- paraphrase-multilingual-MiniLM-L12-v2: 多语言模型,支持中文
|
||||
- paraphrase-multilingual-mpnet-base-v2: 多语言模型,精度高
|
||||
"""
|
||||
self.model_name = model_name
|
||||
self.model = None
|
||||
self._load_model()
|
||||
|
||||
def _load_model(self):
|
||||
"""加载预训练模型"""
|
||||
try:
|
||||
logger.info(f"正在加载语义相似度模型: {self.model_name}")
|
||||
self.model = SentenceTransformer(self.model_name)
|
||||
logger.info("语义相似度模型加载成功")
|
||||
except Exception as e:
|
||||
logger.error(f"加载语义相似度模型失败: {e}")
|
||||
# 回退到简单模型
|
||||
self.model = None
|
||||
|
||||
def calculate_similarity(self, text1: str, text2: str, fast_mode: bool = True) -> float:
|
||||
"""
|
||||
计算两个文本的语义相似度
|
||||
|
||||
Args:
|
||||
text1: 第一个文本
|
||||
text2: 第二个文本
|
||||
fast_mode: 是否使用快速模式(结合传统方法)
|
||||
|
||||
Returns:
|
||||
相似度分数 (0-1之间)
|
||||
"""
|
||||
if not text1 or not text2:
|
||||
return 0.0
|
||||
|
||||
try:
|
||||
# 快速模式:先使用传统方法快速筛选
|
||||
if fast_mode:
|
||||
tfidf_sim = self._calculate_tfidf_similarity(text1, text2)
|
||||
|
||||
# 如果传统方法相似度很高或很低,直接返回
|
||||
if tfidf_sim >= 0.9:
|
||||
return tfidf_sim
|
||||
elif tfidf_sim <= 0.3:
|
||||
return tfidf_sim
|
||||
|
||||
# 中等相似度时,使用语义方法进行精确计算
|
||||
if self.model is not None:
|
||||
semantic_sim = self._calculate_semantic_similarity(text1, text2)
|
||||
# 结合两种方法的结果
|
||||
return (tfidf_sim * 0.3 + semantic_sim * 0.7)
|
||||
else:
|
||||
return tfidf_sim
|
||||
|
||||
# 完整模式:直接使用语义相似度
|
||||
if self.model is not None:
|
||||
return self._calculate_semantic_similarity(text1, text2)
|
||||
else:
|
||||
return self._calculate_tfidf_similarity(text1, text2)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"计算语义相似度失败: {e}")
|
||||
return self._calculate_tfidf_similarity(text1, text2)
|
||||
|
||||
def _calculate_semantic_similarity(self, text1: str, text2: str) -> float:
|
||||
"""使用sentence-transformers计算语义相似度"""
|
||||
try:
|
||||
# 获取文本嵌入向量
|
||||
embeddings = self.model.encode([text1, text2])
|
||||
|
||||
# 计算余弦相似度
|
||||
similarity = self._cosine_similarity(embeddings[0], embeddings[1])
|
||||
|
||||
# 确保结果在0-1范围内
|
||||
similarity = max(0.0, min(1.0, similarity))
|
||||
|
||||
logger.debug(f"语义相似度计算: {similarity:.4f}")
|
||||
return float(similarity)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"语义相似度计算失败: {e}")
|
||||
return self._calculate_tfidf_similarity(text1, text2)
|
||||
|
||||
def _calculate_tfidf_similarity(self, text1: str, text2: str) -> float:
|
||||
"""使用TF-IDF计算相似度(回退方法)"""
|
||||
try:
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
|
||||
vectorizer = TfidfVectorizer(max_features=1000, stop_words=None)
|
||||
vectors = vectorizer.fit_transform([text1, text2])
|
||||
similarity = cosine_similarity(vectors[0:1], vectors[1:2])[0][0]
|
||||
|
||||
logger.debug(f"TF-IDF相似度计算: {similarity:.4f}")
|
||||
return float(similarity)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"TF-IDF相似度计算失败: {e}")
|
||||
return 0.0
|
||||
|
||||
def _cosine_similarity(self, vec1: np.ndarray, vec2: np.ndarray) -> float:
|
||||
"""计算余弦相似度"""
|
||||
try:
|
||||
# 计算点积
|
||||
dot_product = np.dot(vec1, vec2)
|
||||
|
||||
# 计算向量的模长
|
||||
norm1 = np.linalg.norm(vec1)
|
||||
norm2 = np.linalg.norm(vec2)
|
||||
|
||||
# 避免除零错误
|
||||
if norm1 == 0 or norm2 == 0:
|
||||
return 0.0
|
||||
|
||||
# 计算余弦相似度
|
||||
similarity = dot_product / (norm1 * norm2)
|
||||
|
||||
return float(similarity)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"余弦相似度计算失败: {e}")
|
||||
return 0.0
|
||||
|
||||
def batch_calculate_similarity(self, text_pairs: List[Tuple[str, str]]) -> List[float]:
|
||||
"""
|
||||
批量计算相似度
|
||||
|
||||
Args:
|
||||
text_pairs: 文本对列表 [(text1, text2), ...]
|
||||
|
||||
Returns:
|
||||
相似度分数列表
|
||||
"""
|
||||
if not text_pairs:
|
||||
return []
|
||||
|
||||
try:
|
||||
if self.model is not None:
|
||||
return self._batch_semantic_similarity(text_pairs)
|
||||
else:
|
||||
return [self._calculate_tfidf_similarity(t1, t2) for t1, t2 in text_pairs]
|
||||
except Exception as e:
|
||||
logger.error(f"批量相似度计算失败: {e}")
|
||||
return [0.0] * len(text_pairs)
|
||||
|
||||
def _batch_semantic_similarity(self, text_pairs: List[Tuple[str, str]]) -> List[float]:
|
||||
"""批量计算语义相似度"""
|
||||
try:
|
||||
# 提取所有文本
|
||||
all_texts = []
|
||||
for text1, text2 in text_pairs:
|
||||
all_texts.extend([text1, text2])
|
||||
|
||||
# 批量获取嵌入向量
|
||||
embeddings = self.model.encode(all_texts)
|
||||
|
||||
# 计算每对的相似度
|
||||
similarities = []
|
||||
for i in range(0, len(embeddings), 2):
|
||||
similarity = self._cosine_similarity(embeddings[i], embeddings[i+1])
|
||||
similarities.append(float(similarity))
|
||||
|
||||
return similarities
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"批量语义相似度计算失败: {e}")
|
||||
return [self._calculate_tfidf_similarity(t1, t2) for t1, t2 in text_pairs]
|
||||
|
||||
def get_similarity_explanation(self, text1: str, text2: str, similarity: float) -> str:
|
||||
"""
|
||||
获取相似度解释
|
||||
|
||||
Args:
|
||||
text1: 第一个文本
|
||||
text2: 第二个文本
|
||||
similarity: 相似度分数
|
||||
|
||||
Returns:
|
||||
相似度解释文本
|
||||
"""
|
||||
if similarity >= 0.95:
|
||||
return "语义高度相似,建议自动审批"
|
||||
elif similarity >= 0.8:
|
||||
return "语义较为相似,建议人工审核"
|
||||
elif similarity >= 0.6:
|
||||
return "语义部分相似,需要人工判断"
|
||||
elif similarity >= 0.4:
|
||||
return "语义相似度较低,建议重新生成"
|
||||
else:
|
||||
return "语义差异较大,建议重新生成"
|
||||
|
||||
def is_model_available(self) -> bool:
|
||||
"""检查模型是否可用"""
|
||||
return self.model is not None
|
||||
|
||||
# 全局实例
|
||||
_similarity_calculator = None
|
||||
|
||||
def get_similarity_calculator() -> SemanticSimilarityCalculator:
|
||||
"""获取全局相似度计算器实例"""
|
||||
global _similarity_calculator
|
||||
if _similarity_calculator is None:
|
||||
_similarity_calculator = SemanticSimilarityCalculator()
|
||||
return _similarity_calculator
|
||||
|
||||
def calculate_semantic_similarity(text1: str, text2: str, fast_mode: bool = True) -> float:
|
||||
"""
|
||||
计算语义相似度的便捷函数
|
||||
|
||||
Args:
|
||||
text1: 第一个文本
|
||||
text2: 第二个文本
|
||||
fast_mode: 是否使用快速模式
|
||||
|
||||
Returns:
|
||||
相似度分数 (0-1之间)
|
||||
"""
|
||||
calculator = get_similarity_calculator()
|
||||
return calculator.calculate_similarity(text1, text2, fast_mode)
|
||||
|
||||
def batch_calculate_semantic_similarity(text_pairs: List[Tuple[str, str]]) -> List[float]:
|
||||
"""
|
||||
批量计算语义相似度的便捷函数
|
||||
|
||||
Args:
|
||||
text_pairs: 文本对列表
|
||||
|
||||
Returns:
|
||||
相似度分数列表
|
||||
"""
|
||||
calculator = get_similarity_calculator()
|
||||
return calculator.batch_calculate_similarity(text_pairs)
|
||||
@@ -755,10 +755,7 @@ def test_model_response():
|
||||
except Exception as e:
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
@app.route('/feishu-sync')
|
||||
def feishu_sync():
|
||||
"""飞书同步管理页面"""
|
||||
return render_template('feishu_sync.html')
|
||||
# 飞书同步功能已合并到主页面,不再需要单独的路由
|
||||
|
||||
if __name__ == '__main__':
|
||||
import time
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
- `knowledge.py`: 知识库管理相关API
|
||||
- `monitoring.py`: 监控相关API
|
||||
- `system.py`: 系统管理相关API
|
||||
- ~~`feishu_sync.py`~~: 已合并到主仪表板(删除)
|
||||
|
||||
## 蓝图模块说明
|
||||
|
||||
@@ -59,6 +60,12 @@
|
||||
- `/api/backup/*` - 数据备份
|
||||
- `/api/database/status` - 数据库状态
|
||||
|
||||
### 7. 飞书集成功能(已合并)
|
||||
- **原独立页面**: `http://localhost:5000/feishu-sync`
|
||||
- **现集成位置**: 主仪表板的"飞书同步"标签页
|
||||
- **功能**: 飞书多维表格数据同步和管理
|
||||
- **API端点**: 通过主应用路由提供
|
||||
|
||||
## 优势
|
||||
|
||||
1. **模块化**: 每个功能模块独立,便于维护
|
||||
@@ -96,7 +103,16 @@ src/web/
|
||||
│ ├── system.py # 系统管理
|
||||
│ └── README.md # 架构说明
|
||||
├── static/ # 静态文件
|
||||
│ ├── css/
|
||||
│ │ └── style.css # 样式文件(包含飞书集成样式)
|
||||
│ └── js/
|
||||
│ ├── dashboard.js # 仪表板逻辑(包含飞书同步功能)
|
||||
│ ├── chat.js # 对话功能
|
||||
│ └── app.js # 应用主逻辑
|
||||
└── templates/ # 模板文件
|
||||
├── dashboard.html # 主仪表板(包含飞书同步标签页)
|
||||
├── chat.html # 对话页面
|
||||
└── index.html # 首页
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
@@ -106,3 +122,17 @@ src/web/
|
||||
3. 懒加载模式避免启动时的重复初始化
|
||||
4. 错误处理统一在蓝图内部进行
|
||||
5. 保持与原有API接口的兼容性
|
||||
6. 飞书集成功能已从独立蓝图合并到主仪表板
|
||||
7. 前端JavaScript类管理不同功能模块(TSPDashboard、FeishuSyncManager等)
|
||||
|
||||
## 最新更新 (v1.4.0)
|
||||
|
||||
### 功能合并
|
||||
- **飞书同步页面合并**: 原独立的飞书同步页面已合并到主仪表板
|
||||
- **统一用户体验**: 所有功能现在都在一个统一的界面中
|
||||
- **代码优化**: 删除了冗余的蓝图和模板文件
|
||||
|
||||
### 架构改进
|
||||
- **前端模块化**: JavaScript代码按功能模块组织
|
||||
- **数据库扩展**: 工单表新增12个飞书相关字段
|
||||
- **字段映射**: 智能映射飞书字段到本地数据库结构
|
||||
|
||||
@@ -6,11 +6,36 @@
|
||||
|
||||
import os
|
||||
import pandas as pd
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from flask import Blueprint, request, jsonify, send_file
|
||||
from werkzeug.utils import secure_filename
|
||||
from sqlalchemy import text
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 简化的AI准确率配置类
|
||||
class SimpleAIAccuracyConfig:
|
||||
"""简化的AI准确率配置"""
|
||||
def __init__(self):
|
||||
self.auto_approve_threshold = 0.95
|
||||
self.use_human_resolution_threshold = 0.90
|
||||
self.manual_review_threshold = 0.80
|
||||
self.ai_suggestion_confidence = 0.95
|
||||
self.human_resolution_confidence = 0.90
|
||||
|
||||
def should_auto_approve(self, similarity: float) -> bool:
|
||||
return similarity >= self.auto_approve_threshold
|
||||
|
||||
def should_use_human_resolution(self, similarity: float) -> bool:
|
||||
return similarity < self.use_human_resolution_threshold
|
||||
|
||||
def get_confidence_score(self, similarity: float, use_human: bool = False) -> float:
|
||||
if use_human:
|
||||
return self.human_resolution_confidence
|
||||
else:
|
||||
return max(similarity, self.ai_suggestion_confidence)
|
||||
|
||||
from src.main import TSPAssistant
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import WorkOrder, Conversation, WorkOrderSuggestion, KnowledgeEntry
|
||||
@@ -250,51 +275,101 @@ def save_workorder_human_resolution(workorder_id):
|
||||
rec = WorkOrderSuggestion(work_order_id=w.id)
|
||||
session.add(rec)
|
||||
rec.human_resolution = human_text
|
||||
# 计算相似度(使用简单cosine TF-IDF,避免外部服务依赖)
|
||||
# 计算语义相似度(使用sentence-transformers进行更准确的语义比较)
|
||||
try:
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
texts = [rec.ai_suggestion or "", human_text]
|
||||
vec = TfidfVectorizer(max_features=1000)
|
||||
mat = vec.fit_transform(texts)
|
||||
sim = float(cosine_similarity(mat[0:1], mat[1:2])[0][0])
|
||||
except Exception:
|
||||
sim = 0.0
|
||||
from src.utils.semantic_similarity import calculate_semantic_similarity
|
||||
ai_text = rec.ai_suggestion or ""
|
||||
sim = calculate_semantic_similarity(ai_text, human_text)
|
||||
logger.info(f"AI建议与人工描述语义相似度: {sim:.4f}")
|
||||
except Exception as e:
|
||||
logger.error(f"计算语义相似度失败: {e}")
|
||||
# 回退到传统方法
|
||||
try:
|
||||
from sklearn.feature_extraction.text import TfidfVectorizer
|
||||
from sklearn.metrics.pairwise import cosine_similarity
|
||||
texts = [rec.ai_suggestion or "", human_text]
|
||||
vec = TfidfVectorizer(max_features=1000)
|
||||
mat = vec.fit_transform(texts)
|
||||
sim = float(cosine_similarity(mat[0:1], mat[1:2])[0][0])
|
||||
except Exception:
|
||||
sim = 0.0
|
||||
rec.ai_similarity = sim
|
||||
# 自动审批条件≥0.95
|
||||
approved = sim >= 0.95
|
||||
|
||||
# 使用简化的配置
|
||||
config = SimpleAIAccuracyConfig()
|
||||
|
||||
# 自动审批条件
|
||||
approved = config.should_auto_approve(sim)
|
||||
rec.approved = approved
|
||||
|
||||
# 记录使用人工描述入库的标记(当AI准确率低于阈值时)
|
||||
use_human_resolution = config.should_use_human_resolution(sim)
|
||||
rec.use_human_resolution = use_human_resolution
|
||||
|
||||
session.commit()
|
||||
return jsonify({"success": True, "similarity": sim, "approved": approved})
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"similarity": sim,
|
||||
"approved": approved,
|
||||
"use_human_resolution": use_human_resolution
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@workorders_bp.route('/<int:workorder_id>/approve-to-knowledge', methods=['POST'])
|
||||
def approve_workorder_to_knowledge(workorder_id):
|
||||
"""将已审批的AI建议入库为知识条目"""
|
||||
"""将已审批的AI建议或人工描述入库为知识条目"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
w = session.query(WorkOrder).filter(WorkOrder.id == workorder_id).first()
|
||||
if not w:
|
||||
return jsonify({"error": "工单不存在"}), 404
|
||||
|
||||
rec = session.query(WorkOrderSuggestion).filter(WorkOrderSuggestion.work_order_id == w.id).first()
|
||||
if not rec or not rec.approved or not rec.ai_suggestion:
|
||||
return jsonify({"error": "未找到可入库的已审批AI建议"}), 400
|
||||
# 入库为知识条目(问=工单标题;答=AI建议;类目用工单分类)
|
||||
if not rec:
|
||||
return jsonify({"error": "未找到工单建议记录"}), 400
|
||||
|
||||
# 使用简化的配置
|
||||
config = SimpleAIAccuracyConfig()
|
||||
|
||||
# 确定使用哪个内容入库
|
||||
if rec.use_human_resolution and rec.human_resolution:
|
||||
# AI准确率低于阈值,使用人工描述入库
|
||||
answer_content = rec.human_resolution
|
||||
confidence_score = config.get_confidence_score(rec.ai_similarity or 0, use_human=True)
|
||||
verified_by = 'human_resolution'
|
||||
logger.info(f"工单 {workorder_id} 使用人工描述入库,AI相似度: {rec.ai_similarity:.4f}")
|
||||
elif rec.approved and rec.ai_suggestion:
|
||||
# AI准确率≥阈值,使用AI建议入库
|
||||
answer_content = rec.ai_suggestion
|
||||
confidence_score = config.get_confidence_score(rec.ai_similarity or 0, use_human=False)
|
||||
verified_by = 'auto_approve'
|
||||
logger.info(f"工单 {workorder_id} 使用AI建议入库,相似度: {rec.ai_similarity:.4f}")
|
||||
else:
|
||||
return jsonify({"error": "未找到可入库的内容"}), 400
|
||||
|
||||
# 入库为知识条目
|
||||
entry = KnowledgeEntry(
|
||||
question=w.title or (w.description[:20] if w.description else '工单问题'),
|
||||
answer=rec.ai_suggestion,
|
||||
answer=answer_content,
|
||||
category=w.category or '其他',
|
||||
confidence_score=0.95,
|
||||
confidence_score=confidence_score,
|
||||
is_active=True,
|
||||
is_verified=True,
|
||||
verified_by='auto_approve',
|
||||
verified_by=verified_by,
|
||||
verified_at=datetime.now()
|
||||
)
|
||||
session.add(entry)
|
||||
session.commit()
|
||||
return jsonify({"success": True, "knowledge_id": entry.id})
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"knowledge_id": entry.id,
|
||||
"used_content": "human_resolution" if rec.use_human_resolution else "ai_suggestion",
|
||||
"confidence_score": confidence_score
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"入库知识库失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@workorders_bp.route('/import', methods=['POST'])
|
||||
|
||||
@@ -604,64 +604,406 @@ body {
|
||||
color: #6c757d;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
| ||||