operations_project/apps/common/services/chat_service.py
2025-05-07 22:24:02 +08:00

143 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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