feat: 重大功能更新 v1.4.0 - 飞书集成、AI语义相似度、前端优化

主要更新内容:
- 🚀 飞书多维表格集成,支持工单数据同步
- 🤖 AI建议与人工描述语义相似度计算
- 🎨 前端UI全面优化,现代化设计
- 📊 智能知识库入库策略(AI准确率<90%使用人工描述)
- 🔧 代码重构,模块化架构优化
- 📚 完整文档整合和更新
- 🐛 修复配置导入和数据库字段问题

技术特性:
- 使用sentence-transformers进行语义相似度计算
- 快速模式结合TF-IDF和语义方法
- 响应式设计,支持移动端
- 加载状态和动画效果
- 配置化AI准确率阈值
This commit is contained in:
赵杰 Jie Zhao (雄狮汽车科技)
2025-09-19 19:32:42 +01:00
parent 79cf316c63
commit da4736c323
30 changed files with 4778 additions and 1406 deletions

View File

@@ -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个飞书相关字段
- **字段映射**: 智能映射飞书字段到本地数据库结构

View File

@@ -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'])