feat: 优化飞书集成、知识库、Agent、工单管理及AI建议功能,统一前端对话字体样式并移除工单模板文件。

This commit is contained in:
zhaojie
2026-02-11 22:53:08 +08:00
parent f8f3738134
commit d0dd18342f
31 changed files with 1384 additions and 211 deletions

View File

@@ -6,10 +6,12 @@ TSP Agent助手 - 简化版本
import logging
import asyncio
import json
from typing import Dict, Any, List, Optional
from datetime import datetime
from src.config.unified_config import get_config
from src.agent.llm_client import LLMManager
from src.web.service_manager import service_manager
logger = logging.getLogger(__name__)
@@ -304,22 +306,65 @@ class TSPAgentAssistant:
logger.error(f"获取LLM使用统计失败: {e}")
return {}
def process_message_agent_sync(self, message: str, user_id: str = "admin",
work_order_id: Optional[int] = None,
enable_proactive: bool = True) -> Dict[str, Any]:
"""处理消息(同步桥接)"""
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(self.process_message_agent(message, user_id, work_order_id, enable_proactive))
except Exception as e:
logger.error(f"同步处理消息失败: {e}")
return {"error": str(e)}
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]:
"""处理消息"""
"""处理消息 (实战化)"""
try:
# 简化的消息处理
logger.info(f"Agent收到消息: {message}")
# 1. 识别意图和推荐工具
prompt = f"用户消息: {message}\n请分析用户意图,并从工具列表中选择最合适的工具。工具列表: {json.dumps(self.get_available_tools())}\n请直接返回你的分析和建议响应。"
response_text = await self.llm_manager.generate(prompt)
# 2. 模拟动作生成
actions = []
if "工单" in message or "查询" in message:
actions.append({"type": "tool_call", "tool": "search_work_order", "status": "suggested"})
return {
"success": True,
"message": f"Agent收到消息: {message}",
"response": response_text,
"actions": actions,
"user_id": user_id,
"work_order_id": work_order_id,
"status": "completed",
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"处理消息失败: {e}")
return {"error": str(e)}
def execute_tool_sync(self, tool_name: str, parameters: Dict[str, Any] = None) -> Dict[str, Any]:
"""执行工具(同步桥接)"""
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(self.execute_tool(tool_name, parameters))
except Exception as e:
return {"error": str(e)}
def trigger_sample_actions_sync(self) -> Dict[str, Any]:
"""触发示例动作(同步桥接)"""
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(self.trigger_sample_actions())
except Exception as e:
return {"success": False, "error": str(e)}
async def trigger_sample_actions(self) -> Dict[str, Any]:
"""触发示例动作"""
@@ -336,7 +381,7 @@ class TSPAgentAssistant:
logger.error(f"触发示例动作失败: {e}")
return {"success": False, "error": str(e)}
def process_file_to_knowledge(self, file_path: str, filename: str) -> Dict[str, Any]:
async def process_file_to_knowledge(self, file_path: str, filename: str) -> Dict[str, Any]:
"""处理文件并生成知识库"""
try:
import os
@@ -356,20 +401,39 @@ class TSPAgentAssistant:
logger.info(f"文件读取成功: {filename}, 字符数={len(content)}")
# 使用简化的知识提取
# 使用LLM进行知识提取 (异步调用)
logger.info(f"正在对文件内容进行 AI 知识提取...")
knowledge_entries = self._extract_knowledge_from_content(content, filename)
knowledge_entries = await self._extract_knowledge_from_content(content, filename)
logger.info(f"知识提取完成: 共提取出 {len(knowledge_entries)} 个潜在条目")
# 保存到知识库
saved_count = 0
# 获取知识库管理器
try:
knowledge_manager = service_manager.get_assistant().knowledge_manager
except Exception as e:
logger.error(f"无法获取知识库管理器: {e}")
knowledge_manager = None
for i, entry in enumerate(knowledge_entries):
try:
logger.info(f"正在保存知识条目 [{i+1}/{len(knowledge_entries)}]: {entry.get('question', '')[:30]}...")
# 这里在实际项目中应当注入知识库管理器的保存逻辑
# 但在当前简化版本中仅记录日志
saved_count += 1
if knowledge_manager:
# 实际保存到数据库
knowledge_manager.add_knowledge_entry(
question=entry.get('question'),
answer=entry.get('answer'),
category=entry.get('category', '文档导入'),
confidence_score=entry.get('confidence_score', 0.8)
)
saved_count += 1
else:
# 如果无法获取管理器,仅记录日志(降级处理)
logger.warning("知识库管理器不可用,跳过保存")
except Exception as save_error:
logger.error(f"保存知识条目 {i+1} 时出错: {save_error}")
@@ -402,26 +466,71 @@ class TSPAgentAssistant:
logger.error(f"读取文件失败: {e}")
return ""
def _extract_knowledge_from_content(self, content: str, filename: str) -> List[Dict[str, Any]]:
"""从内容中提取知识"""
async def _extract_knowledge_from_content(self, content: str, filename: str) -> List[Dict[str, Any]]:
"""从内容中提取知识 - 使用LLM"""
try:
# 简化的知识提取逻辑
entries = []
# 按段落分割内容
paragraphs = content.split('\n\n')
for i, paragraph in enumerate(paragraphs[:5]): # 最多提取5个
if len(paragraph.strip()) > 20: # 过滤太短的段落
entries.append({
"question": f"关于{filename}的问题{i+1}",
"answer": paragraph.strip(),
"category": "文档知识",
"confidence_score": 0.7
# 限制内容长度避免超出token限制
# 假设每个汉字2个token保留前8000个字符作为上下文
truncated_content = content[:8000]
if len(content) > 8000:
truncated_content += "\n...(后续内容已省略)"
prompt = f"""
你是一个专业的知识库构建助手。请分析以下文档内容,提取出关键的"问题""答案"对,用于构建知识库。
文档文件名:{filename}
文档内容:
{truncated_content}
要求:
1. 提取文档中的核心知识点,转化为"问题(question)""答案(answer)"的形式。
2. "问题"应该清晰明确,方便用户搜索。
3. "答案"应该准确、完整,直接回答问题。
4. "分类(category)"请根据内容自动归类(如:故障排查、操作指南、系统配置、业务流程等)。
5. 输出格式必须是合法的 JSON 数组不要包含Markdown标记。
JSON格式示例
[
{{"question": "如何重置密码?", "answer": "请访问设置页面,点击重置密码按钮...", "category": "操作指南"}},
{{"question": "系统支持哪些浏览器?", "answer": "支持Chrome, Edge, Firefox...", "category": "系统配置"}}
]
"""
# 调用LLM生成
logger.info("正在调用LLM进行知识提取...")
response_text = await self.llm_manager.generate(prompt, temperature=0.3)
# 清理响应中的Markdown标记如果存在
cleaned_text = response_text.strip()
if cleaned_text.startswith("```json"):
cleaned_text = cleaned_text[7:]
if cleaned_text.startswith("```"):
cleaned_text = cleaned_text[3:]
if cleaned_text.endswith("```"):
cleaned_text = cleaned_text[:-3]
cleaned_text = cleaned_text.strip()
# 解析JSON
try:
entries = json.loads(cleaned_text)
except json.JSONDecodeError:
# 尝试修复常见的JSON错误
logger.warning(f"JSON解析失败尝试简单修复: {cleaned_text[:100]}...")
# 这里可以添加更复杂的修复逻辑,或者直接记录错误
return []
# 验证和标准化
valid_entries = []
for entry in entries:
if isinstance(entry, dict) and "question" in entry and "answer" in entry:
valid_entries.append({
"question": entry["question"],
"answer": entry["answer"],
"category": entry.get("category", "文档导入"),
"confidence_score": 0.9 # LLM生成的置信度较高
})
return entries
return valid_entries
except Exception as e:
logger.error(f"提取知识失败: {e}")
return []