286 lines
8.2 KiB
Python
286 lines
8.2 KiB
Python
"""
|
|
对话列表管理 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)
|
|
}
|
|
)
|
|
|