更新后台管理消息列表;

This commit is contained in:
karlcarlo
2025-12-15 17:44:35 +08:00
parent 41d2d893d3
commit a7b3454f61
22 changed files with 1620 additions and 356 deletions

View File

@@ -1,6 +1,6 @@
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from typing import List, Optional
from typing import List, Optional, Dict, Any
import httpx
import os
import logging
@@ -23,6 +23,10 @@ class Message(BaseModel):
class ChatRequest(BaseModel):
message: str
conversation_id: Optional[str] = None
enhanced_prompt: Optional[str] = None # 前端生成的完整提示词
customer_tags: Optional[List[Dict[str, Any]]] = None # 客户标签
message_history: Optional[List[Dict[str, Any]]] = None # 企业微信历史消息
workflow_context: Optional[Dict[str, Any]] = None # 工作流上下文
class ChatResponse(BaseModel):
@@ -194,44 +198,233 @@ async def update_role_config(
@router.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest, service: GLMService = Depends(get_glm_service)):
"""处理聊天请求"""
# 创建或获取对话历史
# 步骤1: 记录请求开始
logger.info(
f"收到聊天请求: conversation_id={request.conversation_id or 'None'}, "
f"message_length={len(request.message)}, "
f"message_preview='{request.message[:50]}{'...' if len(request.message) > 50 else ''}'"
)
# 记录增强参数信息
has_enhanced_prompt = request.enhanced_prompt is not None
has_customer_tags = (
request.customer_tags is not None and len(request.customer_tags) > 0
)
has_message_history = (
request.message_history is not None and len(request.message_history) > 0
)
has_workflow_context = request.workflow_context is not None
logger.info(
f"增强参数状态: enhanced_prompt={has_enhanced_prompt}, "
f"customer_tags={has_customer_tags} ({len(request.customer_tags) if has_customer_tags else 0}个标签), "
f"message_history={has_message_history} ({len(request.message_history) if has_message_history else 0}条历史), "
f"workflow_context={has_workflow_context}"
)
# 记录客户标签摘要
if has_customer_tags:
tag_categories = {}
for tag in request.customer_tags:
category = tag.get("TagCategory", "未分类")
name = tag.get("TagName", "未命名")
if category not in tag_categories:
tag_categories[category] = []
tag_categories[category].append(name)
tag_summary = []
for category, names in tag_categories.items():
tag_summary.append(
f"{category}: {', '.join(names[:3])}{'...' if len(names) > 3 else ''}"
)
# 检查是否使用mock数据
is_mock_data = False
for tag in request.customer_tags:
if tag.get("TagName", "").startswith("mock_") or tag.get(
"TagCategory", ""
).startswith("mock_"):
is_mock_data = True
break
mock_note = " [mock数据]" if is_mock_data else ""
logger.info(f"客户标签摘要{mock_note}: {', '.join(tag_summary)}")
# 记录历史消息摘要
if has_message_history:
# 按时间排序,获取最近的消息
sorted_history = sorted(
request.message_history, key=lambda x: x.get("msgtime", ""), reverse=True
)[
:5
] # 只显示最近5条
history_summary = []
for i, msg in enumerate(sorted_history):
from_user = msg.get("from_user", "未知用户")
user_id = (
msg.get("user_id")
or msg.get("userId")
or msg.get("from_user_id")
or "无ID"
)
content = msg.get("text", {}).get("content", "") or msg.get("content", "")
content_preview = content[:30] + ("..." if len(content) > 30 else "")
history_summary.append(f"{from_user}(ID:{user_id}): '{content_preview}'")
# 检查是否使用mock数据
is_mock_data = False
for msg in sorted_history:
if msg.get("from_user", "").startswith("mock_") or msg.get(
"user_id", ""
).startswith("mock_"):
is_mock_data = True
break
mock_note = " [mock数据]" if is_mock_data else ""
logger.info(f"历史消息摘要{mock_note}: {', '.join(history_summary)}")
# 步骤2: 创建或获取对话历史
if request.conversation_id and request.conversation_id in conversations:
conversation_history = conversations[request.conversation_id]
logger.info(
f"使用现有对话: {request.conversation_id}, 历史消息数: {len(conversation_history)}"
)
# 记录历史消息摘要
if conversation_history:
last_messages = conversation_history[-3:] # 显示最近3条消息
history_summary = []
for i, msg in enumerate(last_messages, 1):
role = msg["role"]
content_preview = msg["content"][:30] + (
"..." if len(msg["content"]) > 30 else ""
)
history_summary.append(f"{role}: '{content_preview}'")
logger.debug(f"最近历史消息摘要: {', '.join(history_summary)}")
else:
conversation_history = []
request.conversation_id = f"conv_{len(conversations) + 1}"
conversations[request.conversation_id] = conversation_history
logger.info(f"新建对话: {request.conversation_id}")
# 获取当前角色配置
# 步骤3: 构建系统提示词
try:
role = await service.get_current_role()
system_prompt = build_system_prompt(role.to_role_config_dict())
except Exception as e:
logger.error(f"获取角色配置失败: {e}")
raise HTTPException(status_code=500, detail=f"获取角色配置失败: {str(e)}")
if has_enhanced_prompt:
# 使用前端生成的增强提示词
system_prompt = request.enhanced_prompt
logger.info(f"使用前端增强提示词, 长度: {len(system_prompt)} 字符")
logger.debug(
f"增强提示词预览: '{system_prompt[:200]}{'...' if len(system_prompt) > 200 else ''}'"
)
else:
# 获取当前角色配置并构建系统提示词
role = await service.get_current_role()
role_config = role.to_role_config_dict()
logger.info(
f"获取角色配置: name='{role.name}', "
f"技能数: {len(role_config['skills'].split('\\n')) if role_config['skills'] else 0}, "
f"限制数: {len(role_config['restrictions'].split('\\n')) if role_config['restrictions'] else 0}"
)
# 构建消息列表
system_prompt = build_system_prompt(role_config)
logger.debug(f"系统提示词构建完成, 长度: {len(system_prompt)} 字符")
except Exception as e:
logger.error(
f"构建系统提示词失败: {e}, conversation_id={request.conversation_id}"
)
raise HTTPException(status_code=500, detail=f"构建系统提示词失败: {str(e)}")
# 步骤4: 构建消息列表
messages = [{"role": "system", "content": system_prompt}]
# 添加历史消息
for msg in conversation_history[-10:]: # 保留最近10条历史
# 初始化企业微信历史消息变量
selected_wework_messages = []
# 添加企业微信历史消息(如果提供)
if has_message_history:
logger.info(f"添加企业微信历史消息到上下文: {len(request.message_history)} 条")
# 将企业微信消息转换为大模型消息格式
wework_messages = []
for msg in request.message_history:
from_user = msg.get("from_user", "未知用户")
content = msg.get("text", {}).get("content", "") or msg.get("content", "")
msgtime = msg.get("msgtime", "")
if content:
# 确定角色:如果是客户发送的,则为user;否则为assistant
# 这里需要根据实际业务逻辑判断,暂时假设外部用户是user
role = (
"user"
if "customer" in from_user.lower() or "user" in from_user.lower()
else "assistant"
)
# 格式化消息内容
formatted_content = f"[{msgtime}] {from_user}: {content}"
wework_messages.append({"role": role, "content": formatted_content})
# 添加到消息列表(限制数量,避免过长)
max_wework_messages = 10
selected_wework_messages = wework_messages[
-max_wework_messages:
] # 取最近的消息
messages.extend(selected_wework_messages)
logger.info(
f"已添加 {len(selected_wework_messages)} 条企业微信历史消息到上下文"
)
# 添加与大模型的对话历史
history_messages = conversation_history[-10:] # 保留最近10条历史
for msg in history_messages:
messages.append({"role": msg["role"], "content": msg["content"]})
# 添加当前用户消息
messages.append({"role": "user", "content": request.message})
conversation_history.append({"role": "user", "content": request.message})
# 调用DeepSeek API
logger.info(
f"构建消息列表完成: 系统消息1条, 企业微信历史{len(selected_wework_messages)}条, "
f"对话历史{len(history_messages)}条, 用户消息1条, 总消息数: {len(messages)}"
)
# 记录消息列表摘要
if logger.isEnabledFor(logging.DEBUG):
for i, msg in enumerate(messages):
role = msg["role"]
content_preview = msg["content"][:50] + (
"..." if len(msg["content"]) > 50 else ""
)
logger.debug(f"消息{i+1}: {role} - '{content_preview}'")
# 步骤5: 调用DeepSeek API
try:
logger.info(
f"调用DeepSeek API, conversation_id={request.conversation_id}, 总消息数: {len(messages)}"
)
response_text = await call_deepseek_api(messages)
# 步骤6: 记录API响应
logger.info(
f"DeepSeek API调用成功, conversation_id={request.conversation_id}, "
f"响应长度: {len(response_text)} 字符, "
f"响应预览: '{response_text[:100]}{'...' if len(response_text) > 100 else ''}'"
)
# 添加助手回复到历史
conversation_history.append({"role": "assistant", "content": response_text})
# 步骤7: 返回响应
logger.info(
f"返回聊天响应: conversation_id={request.conversation_id}, 响应长度: {len(response_text)} 字符"
)
return ChatResponse(
response=response_text, conversation_id=request.conversation_id
)
except Exception as e:
logger.error(
f"DeepSeek API调用失败: {e}, conversation_id={request.conversation_id}, message_preview='{request.message[:50]}...'"
)
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -135,6 +135,40 @@ async def get_message_stats(service: MessageService = Depends(get_message_servic
raise HTTPException(status_code=500, detail=f"获取消息统计失败: {str(e)}")
@router.get("/config")
async def get_message_config():
"""
获取消息服务配置信息
返回企业微信SDK配置、文件路径等基本信息
"""
try:
import os
from pathlib import Path
# 从环境变量获取配置
corpid = os.getenv("CORPID", "")
secret = os.getenv("WEWORK_SECRET", "")
# 构建文件路径
backend_dir = Path(__file__).parent.parent.parent
lib_path = backend_dir / "lib" / "sdk" / "libWeWorkFinanceSdk_C.so"
data_dir = backend_dir / "data"
config = {
"corpid": corpid,
# "secret": secret[:10] + "..." if secret else "", # 只显示前10个字符
"libPath": str(lib_path),
"dataDir": str(data_dir),
}
return {"success": True, "message": "配置获取成功", "data": config}
except Exception as e:
logger.error(f"获取配置信息失败: {e}")
raise HTTPException(status_code=500, detail=f"获取配置信息失败: {str(e)}")
@router.get("/{msgid}")
async def get_message_by_id(
msgid: str, service: MessageService = Depends(get_message_service)
@@ -150,13 +184,3 @@ async def get_message_by_id(
except Exception as e:
logger.error(f"查询消息详情失败 (msgid: {msgid}): {e}")
raise HTTPException(status_code=500, detail=f"查询消息详情失败: {str(e)}")
# 应用关闭时的清理
@router.on_event("shutdown")
async def shutdown_event():
"""应用关闭时清理资源"""
from app.services.message_service import close_message_service
close_message_service()
logger.info("消息服务已关闭")