operations_project/apps/chat/chat_service.py

142 lines
5.6 KiB
Python
Raw Normal View History

2025-05-07 18:01:48 +08:00
# apps/common/services/chat_service.py
import logging
import json
from uuid import uuid4
from django.db import transaction
from apps.accounts.models import User
from apps.knowledge_base.models import KnowledgeBase
from apps.chat.models import ChatHistory
from apps.permissions.services.permission_service import KnowledgeBasePermissionMixin
logger = logging.getLogger(__name__)
class ChatService(KnowledgeBasePermissionMixin):
@transaction.atomic
def create_chat_record(self, user, data, conversation_id=None):
"""创建聊天记录供chat、gmail、feishu模块复用"""
try:
# 验证必填字段
if 'question' not in data:
raise ValueError("缺少必填字段: question")
# 如果未提供conversation_id生成新的
if not conversation_id:
conversation_id = str(uuid4())
logger.info(f"生成新的会话ID: {conversation_id}")
# 处理知识库ID
dataset_ids = []
if 'dataset_id' in data:
dataset_ids.append(str(data['dataset_id']))
elif 'dataset_id_list' in data:
if isinstance(data['dataset_id_list'], str):
try:
dataset_list = json.loads(data['dataset_id_list'])
dataset_ids = [str(id) for id in dataset_list if isinstance(dataset_list, list)]
except json.JSONDecodeError:
dataset_ids = [str(data['dataset_id_list'])]
else:
dataset_ids = [str(id) for id in data['dataset_id_list']]
if not dataset_ids:
raise ValueError("缺少必填字段: dataset_id 或 dataset_id_list")
# 验证知识库权限
knowledge_bases = []
external_id_list = []
for kb_id in dataset_ids:
knowledge_base = KnowledgeBase.objects.filter(id=kb_id).first()
if not knowledge_base:
raise ValueError(f"知识库不存在: {kb_id}")
if not self.check_knowledge_base_permission(knowledge_base, user, 'read'):
raise ValueError(f"无权访问知识库: {knowledge_base.name}")
knowledge_bases.append(knowledge_base)
if knowledge_base.external_id:
external_id_list.append(str(knowledge_base.external_id))
# 创建metadata
metadata = {
'model_id': data.get('model_id', '7a214d0e-e65e-11ef-9f4a-0242ac120006'),
'dataset_id_list': dataset_ids,
'dataset_external_id_list': external_id_list,
'dataset_names': [kb.name for kb in knowledge_bases]
}
# 设置标题
title = data.get('title', 'New chat')
# 创建用户问题记录
question_record = ChatHistory.objects.create(
user=user,
knowledge_base=knowledge_bases[0], # 使用第一个知识库
conversation_id=conversation_id,
title=title,
role='user',
content=data['question'],
metadata=metadata
)
return question_record, conversation_id, metadata, knowledge_bases, external_id_list
except Exception as e:
logger.error(f"创建聊天记录失败: {str(e)}")
raise
def get_conversation_detail(self, user, conversation_id):
"""获取会话详情供chat、gmail、feishu模块复用"""
try:
# 获取用户有权限的知识库ID
accessible_kb_ids = [
kb.id for kb in KnowledgeBase.objects.all()
if self.check_knowledge_base_permission(kb, user, 'read')
]
# 查询会话记录
messages = ChatHistory.objects.filter(
conversation_id=conversation_id,
is_deleted=False
).filter(
Q(user=user) | Q(knowledge_base_id__in=accessible_kb_ids)
).order_by('created_at')
if not messages.exists():
raise ValueError("对话不存在或无权限")
# 获取知识库信息
first_message = messages.first()
dataset_info = []
if first_message and first_message.metadata and 'dataset_id_list' in first_message.metadata:
datasets = KnowledgeBase.objects.filter(id__in=first_message.metadata['dataset_id_list'])
accessible_datasets = [
ds for ds in datasets if self.check_knowledge_base_permission(ds, user, 'read')
]
dataset_info = [
{'id': str(ds.id), 'name': ds.name, 'type': ds.type}
for ds in accessible_datasets
]
# 构建消息列表
message_list = [
{
'id': str(msg.id),
'parent_id': msg.parent_id,
'role': msg.role,
'content': msg.content,
'created_at': msg.created_at.strftime('%Y-%m-%d %H:%M:%S'),
'metadata': msg.metadata
}
for msg in messages
]
return {
'conversation_id': conversation_id,
'datasets': dataset_info,
'messages': message_list
}
except Exception as e:
logger.error(f"获取会话详情失败: {str(e)}")
raise