Files
moss-ai/app/backend-python/api/conversation.py

286 lines
8.2 KiB
Python
Raw Permalink Normal View History

2025-12-15 22:05:56 +08:00
"""
对话列表管理 API 路由
"""
import logging
from uuid import uuid4
from fastapi import APIRouter, HTTPException, status, Query
from typing import Optional
from pydantic import BaseModel, Field
from services.conversation_service import conversation_service
from services.chat_history_service import chat_history_service
logger = logging.getLogger(__name__)
router = APIRouter()
# ==================== 请求/响应模型 ====================
class CreateConversationRequest(BaseModel):
system_user_id: int = Field(..., description="系统用户ID")
title: str = Field(default="新对话", description="对话标题")
description: Optional[str] = Field(None, description="对话描述")
class Config:
json_schema_extra = {
"example": {
"system_user_id": 1000000001,
"title": "智能家居控制",
"description": "关于空调和灯光的对话"
}
}
class UpdateConversationRequest(BaseModel):
context_id: str = Field(..., description="会话上下文ID")
title: Optional[str] = Field(None, description="新标题")
class Config:
json_schema_extra = {
"example": {
"context_id": "session-abc123",
"title": "空调温度调节"
}
}
class DeleteConversationRequest(BaseModel):
context_id: str = Field(..., description="会话上下文ID")
system_user_id: int = Field(..., description="系统用户ID")
class Config:
json_schema_extra = {
"example": {
"context_id": "session-abc123",
"system_user_id": 1000000001
}
}
# ==================== API 端点 ====================
@router.post("/conversations/create")
async def create_conversation(request: CreateConversationRequest):
"""
创建新对话
"""
try:
# 生成新的 context_id
context_id = f"session-{uuid4().hex[:16]}"
logger.info(f"📝 创建新对话: user={request.system_user_id}, title={request.title}")
conversation = await conversation_service.create_conversation(
system_user_id=request.system_user_id,
context_id=context_id,
title=request.title,
description=request.description
)
logger.info(f"✅ 创建对话成功: context={context_id}")
return {
"success": True,
"message": "创建对话成功",
"data": conversation
}
except Exception as e:
logger.error(f"❌ 创建对话失败: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "CreateConversationError",
"message": str(e)
}
)
@router.get("/conversations/list")
async def get_conversations(
system_user_id: int = Query(..., description="系统用户ID"),
limit: int = Query(50, description="返回数量限制"),
only_active: bool = Query(True, description="是否只返回活跃对话")
):
"""
获取用户的对话列表
"""
try:
logger.info(f"📋 获取对话列表: user={system_user_id}, limit={limit}")
conversations = await conversation_service.get_user_conversations(
system_user_id=system_user_id,
limit=limit,
only_active=only_active
)
return {
"success": True,
"message": "获取对话列表成功",
"data": conversations,
"total": len(conversations)
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "GetConversationsError",
"message": str(e)
}
)
@router.get("/conversations/{context_id}")
async def get_conversation(context_id: str):
"""
获取指定对话的详细信息
"""
try:
logger.info(f"🔍 获取对话详情: context={context_id}")
conversation = await conversation_service.get_conversation_by_context(context_id)
if not conversation:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={
"error": "ConversationNotFound",
"message": f"对话不存在: {context_id}"
}
)
return {
"success": True,
"message": "获取对话详情成功",
"data": conversation
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "GetConversationError",
"message": str(e)
}
)
@router.put("/conversations/update")
async def update_conversation(request: UpdateConversationRequest):
"""
更新对话信息如标题
"""
try:
success = await conversation_service.update_conversation(
context_id=request.context_id,
title=request.title
)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={
"error": "ConversationNotFound",
"message": f"对话不存在: {request.context_id}"
}
)
return {
"success": True,
"message": "更新对话成功"
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "UpdateConversationError",
"message": str(e)
}
)
@router.delete("/conversations/delete")
async def delete_conversation(request: DeleteConversationRequest):
"""
删除对话软删除
"""
try:
success = await conversation_service.delete_conversation(
context_id=request.context_id,
system_user_id=request.system_user_id,
soft_delete=True
)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail={
"error": "ConversationNotFound",
"message": f"对话不存在或无权限: {request.context_id}"
}
)
return {
"success": True,
"message": "删除对话成功"
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "DeleteConversationError",
"message": str(e)
}
)
@router.get("/conversations/{context_id}/history")
async def get_conversation_history(
context_id: str,
system_user_id: int = Query(..., description="系统用户ID"),
limit: int = Query(50, description="返回消息数量限制")
):
"""
获取指定对话的历史消息
"""
try:
logger.info(f"📜 获取对话历史: context={context_id}, limit={limit}")
messages = await chat_history_service.get_conversation_history(
system_user_id=system_user_id,
context_id=context_id,
limit=limit
)
# 确保是列表,然后反转顺序,使得最旧的消息在前
messages = list(messages) if not isinstance(messages, list) else messages
messages.reverse()
return {
"success": True,
"message": "获取对话历史成功",
"data": messages,
"total": len(messages)
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={
"error": "GetConversationHistoryError",
"message": str(e)
}
)