大改,未验证
This commit is contained in:
@@ -11,7 +11,7 @@ from datetime import datetime, timedelta
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..core.database import db_manager
|
||||
from ..core.models import Conversation, WorkOrder, WorkOrderSuggestion, KnowledgeEntry
|
||||
from ..core.models import Conversation, WorkOrder, WorkOrderSuggestion, KnowledgeEntry, ChatSession
|
||||
from ..core.redis_manager import redis_manager
|
||||
from src.config.unified_config import get_config
|
||||
from sqlalchemy import and_, or_, desc
|
||||
@@ -45,7 +45,8 @@ class ConversationHistoryManager:
|
||||
response_time: Optional[float] = None,
|
||||
knowledge_used: Optional[List[int]] = None,
|
||||
ip_address: Optional[str] = None,
|
||||
invocation_method: Optional[str] = None
|
||||
invocation_method: Optional[str] = None,
|
||||
session_id: Optional[str] = None
|
||||
) -> int:
|
||||
"""保存对话记录到数据库和Redis"""
|
||||
conversation_id = 0
|
||||
@@ -54,6 +55,7 @@ class ConversationHistoryManager:
|
||||
# 保存到数据库
|
||||
with db_manager.get_session() as session:
|
||||
conversation = Conversation(
|
||||
session_id=session_id,
|
||||
work_order_id=work_order_id,
|
||||
user_message=user_message,
|
||||
assistant_response=assistant_response,
|
||||
@@ -715,3 +717,130 @@ class ConversationHistoryManager:
|
||||
except Exception as e:
|
||||
logger.error(f"获取对话分析数据失败: {e}")
|
||||
return {}
|
||||
|
||||
# ==================== 会话管理方法 ====================
|
||||
|
||||
def get_sessions_paginated(
|
||||
self,
|
||||
page: int = 1,
|
||||
per_page: int = 20,
|
||||
status: Optional[str] = None,
|
||||
search: str = '',
|
||||
date_filter: str = ''
|
||||
) -> Dict[str, Any]:
|
||||
"""分页获取会话列表"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
query = session.query(ChatSession)
|
||||
|
||||
if status:
|
||||
query = query.filter(ChatSession.status == status)
|
||||
|
||||
if search:
|
||||
query = query.filter(
|
||||
or_(
|
||||
ChatSession.title.contains(search),
|
||||
ChatSession.session_id.contains(search),
|
||||
ChatSession.user_id.contains(search)
|
||||
)
|
||||
)
|
||||
|
||||
if date_filter:
|
||||
now = datetime.now()
|
||||
if date_filter == 'today':
|
||||
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
elif date_filter == 'week':
|
||||
start_date = now - timedelta(days=7)
|
||||
elif date_filter == 'month':
|
||||
start_date = now - timedelta(days=30)
|
||||
else:
|
||||
start_date = None
|
||||
if start_date:
|
||||
query = query.filter(ChatSession.created_at >= start_date)
|
||||
|
||||
total = query.count()
|
||||
sessions_list = query.order_by(
|
||||
ChatSession.updated_at.desc()
|
||||
).offset((page - 1) * per_page).limit(per_page).all()
|
||||
|
||||
result = []
|
||||
for s in sessions_list:
|
||||
result.append(s.to_dict())
|
||||
|
||||
return {
|
||||
'sessions': result,
|
||||
'page': page,
|
||||
'per_page': per_page,
|
||||
'total': total,
|
||||
'total_pages': (total + per_page - 1) // per_page
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取会话列表失败: {e}")
|
||||
return {'sessions': [], 'page': page, 'per_page': per_page, 'total': 0, 'total_pages': 0}
|
||||
|
||||
def get_session_messages(
|
||||
self,
|
||||
session_id: str,
|
||||
limit: int = 100,
|
||||
offset: int = 0
|
||||
) -> Dict[str, Any]:
|
||||
"""获取某个会话的所有消息(按时间正序)"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
# 获取会话元数据
|
||||
chat_session = session.query(ChatSession).filter(
|
||||
ChatSession.session_id == session_id
|
||||
).first()
|
||||
|
||||
if not chat_session:
|
||||
return {'error': '会话不存在'}
|
||||
|
||||
# 获取消息
|
||||
messages = session.query(Conversation).filter(
|
||||
Conversation.session_id == session_id
|
||||
).order_by(Conversation.timestamp.asc()).offset(offset).limit(limit).all()
|
||||
|
||||
message_list = []
|
||||
for msg in messages:
|
||||
message_list.append({
|
||||
'id': msg.id,
|
||||
'user_message': msg.user_message,
|
||||
'assistant_response': msg.assistant_response,
|
||||
'timestamp': msg.timestamp.isoformat() if msg.timestamp else None,
|
||||
'confidence_score': msg.confidence_score,
|
||||
'response_time': msg.response_time,
|
||||
'knowledge_used': json.loads(msg.knowledge_used) if msg.knowledge_used else [],
|
||||
})
|
||||
|
||||
return {
|
||||
'session': chat_session.to_dict(),
|
||||
'messages': message_list,
|
||||
'total': len(message_list)
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取会话消息失败: {e}")
|
||||
return {'error': str(e)}
|
||||
|
||||
def delete_session(self, session_id: str) -> bool:
|
||||
"""删除会话及其所有消息"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
# 删除关联消息
|
||||
session.query(Conversation).filter(
|
||||
Conversation.session_id == session_id
|
||||
).delete(synchronize_session=False)
|
||||
|
||||
# 删除会话
|
||||
session.query(ChatSession).filter(
|
||||
ChatSession.session_id == session_id
|
||||
).delete(synchronize_session=False)
|
||||
|
||||
session.commit()
|
||||
logger.info(f"删除会话成功: {session_id}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"删除会话失败: {e}")
|
||||
return False
|
||||
|
||||
@@ -13,7 +13,7 @@ from dataclasses import dataclass
|
||||
from ..core.llm_client import QwenClient
|
||||
from ..knowledge_base.knowledge_manager import KnowledgeManager
|
||||
from ..core.database import db_manager
|
||||
from ..core.models import Conversation, WorkOrder
|
||||
from ..core.models import Conversation, WorkOrder, ChatSession
|
||||
from ..vehicle.vehicle_data_manager import VehicleDataManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -54,6 +54,21 @@ class RealtimeChatManager:
|
||||
|
||||
self.active_sessions[session_id] = session_data
|
||||
self.message_history[session_id] = []
|
||||
|
||||
# 持久化会话到数据库
|
||||
try:
|
||||
with db_manager.get_session() as db_session:
|
||||
chat_session = ChatSession(
|
||||
session_id=session_id,
|
||||
user_id=user_id,
|
||||
work_order_id=work_order_id,
|
||||
status="active",
|
||||
message_count=0,
|
||||
)
|
||||
db_session.add(chat_session)
|
||||
db_session.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"持久化会话记录失败(不影响使用): {e}")
|
||||
|
||||
logger.info(f"创建新会话: {session_id}")
|
||||
return session_id
|
||||
@@ -356,7 +371,7 @@ class RealtimeChatManager:
|
||||
"""保存对话到数据库"""
|
||||
try:
|
||||
with db_manager.get_session() as session:
|
||||
# 统一为一条记录:包含用户消息与助手回复
|
||||
# 计算响应时间
|
||||
try:
|
||||
response_time = None
|
||||
if assistant_msg.timestamp and user_msg.timestamp:
|
||||
@@ -364,26 +379,36 @@ class RealtimeChatManager:
|
||||
except Exception:
|
||||
response_time = None
|
||||
|
||||
# 在知识字段中打上会话标记,便于结束时合并清理
|
||||
marked_knowledge = assistant_msg.knowledge_used or []
|
||||
try:
|
||||
marked_knowledge = list(marked_knowledge)
|
||||
marked_knowledge.append({"session_id": session_id, "type": "session_marker"})
|
||||
except Exception:
|
||||
pass
|
||||
# 保存知识库使用记录(不再塞 session_marker)
|
||||
knowledge_data = assistant_msg.knowledge_used or []
|
||||
|
||||
conversation = Conversation(
|
||||
session_id=session_id,
|
||||
work_order_id=assistant_msg.work_order_id or user_msg.work_order_id,
|
||||
user_message=user_msg.content or "",
|
||||
assistant_response=assistant_msg.content or "",
|
||||
timestamp=assistant_msg.timestamp or user_msg.timestamp,
|
||||
confidence_score=assistant_msg.confidence_score,
|
||||
knowledge_used=json.dumps(marked_knowledge, ensure_ascii=False) if marked_knowledge else None,
|
||||
knowledge_used=json.dumps(knowledge_data, ensure_ascii=False) if knowledge_data else None,
|
||||
response_time=response_time,
|
||||
ip_address=ip_address,
|
||||
invocation_method=invocation_method
|
||||
)
|
||||
session.add(conversation)
|
||||
|
||||
# 更新会话元数据
|
||||
chat_session = session.query(ChatSession).filter(
|
||||
ChatSession.session_id == session_id
|
||||
).first()
|
||||
if chat_session:
|
||||
chat_session.message_count = (chat_session.message_count or 0) + 1
|
||||
chat_session.updated_at = datetime.now()
|
||||
chat_session.source = invocation_method
|
||||
chat_session.ip_address = ip_address
|
||||
# 首条消息时设置会话标题
|
||||
if chat_session.message_count == 1 and user_msg.content:
|
||||
chat_session.title = user_msg.content[:100]
|
||||
|
||||
session.commit()
|
||||
|
||||
except Exception as e:
|
||||
@@ -470,57 +495,21 @@ class RealtimeChatManager:
|
||||
def end_session(self, session_id: str) -> bool:
|
||||
"""结束会话"""
|
||||
try:
|
||||
if session_id in self.active_sessions:
|
||||
session_meta = self.active_sessions[session_id]
|
||||
# 汇总本会话为一条记录
|
||||
history = self.message_history.get(session_id, [])
|
||||
if history:
|
||||
user_parts = []
|
||||
assistant_parts = []
|
||||
response_times = []
|
||||
first_ts = None
|
||||
last_ts = None
|
||||
for i in range(len(history)):
|
||||
msg = history[i]
|
||||
if first_ts is None:
|
||||
first_ts = msg.timestamp
|
||||
last_ts = msg.timestamp
|
||||
if msg.role == "user":
|
||||
user_parts.append(msg.content)
|
||||
# 计算到下一条助手回复的间隔
|
||||
if i + 1 < len(history) and history[i+1].role == "assistant":
|
||||
try:
|
||||
rt = max(0.0, (history[i+1].timestamp - msg.timestamp).total_seconds() * 1000.0)
|
||||
response_times.append(rt)
|
||||
except Exception:
|
||||
pass
|
||||
elif msg.role == "assistant":
|
||||
assistant_parts.append(msg.content)
|
||||
agg_user = "\n\n".join([p for p in user_parts if p])
|
||||
agg_assistant = "\n\n".join([p for p in assistant_parts if p])
|
||||
avg_rt = sum(response_times)/len(response_times) if response_times else None
|
||||
|
||||
from ..core.database import db_manager as _db
|
||||
from ..core.models import Conversation as _Conv
|
||||
import json as _json
|
||||
with _db.get_session() as dbs:
|
||||
agg = _Conv(
|
||||
work_order_id=session_meta.get("work_order_id"),
|
||||
user_message=agg_user,
|
||||
assistant_response=agg_assistant,
|
||||
timestamp=last_ts or first_ts,
|
||||
confidence_score=None,
|
||||
knowledge_used=_json.dumps({"session_id": session_id, "aggregated": True}, ensure_ascii=False),
|
||||
response_time=avg_rt
|
||||
)
|
||||
dbs.add(agg)
|
||||
# 删除本会话标记的分散记录
|
||||
try:
|
||||
pattern = f'%"session_id":"{session_id}"%'
|
||||
dbs.query(_Conv).filter(_Conv.knowledge_used.like(pattern)).delete(synchronize_session=False)
|
||||
except Exception:
|
||||
pass
|
||||
# 更新数据库中的会话状态
|
||||
try:
|
||||
with db_manager.get_session() as dbs:
|
||||
chat_session = dbs.query(ChatSession).filter(
|
||||
ChatSession.session_id == session_id
|
||||
).first()
|
||||
if chat_session:
|
||||
chat_session.status = "ended"
|
||||
chat_session.ended_at = datetime.now()
|
||||
dbs.commit()
|
||||
except Exception as e:
|
||||
logger.warning(f"更新会话状态失败: {e}")
|
||||
|
||||
# 清理内存
|
||||
if session_id in self.active_sessions:
|
||||
del self.active_sessions[session_id]
|
||||
|
||||
if session_id in self.message_history:
|
||||
|
||||
Reference in New Issue
Block a user