Unverified Commit 28ce2b74 authored by uuo00_n's avatar uuo00_n Committed by GitHub

Merge pull request #13 from uuo00n/feature/conversation-unify-and-title-delete-cors

feat: 对话 ID/标题统一、敏感词结构化、删除接口与 CORS 支持
parents aea76f67 789fdcbe
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from typing import List from typing import List
from app.api.deps import get_current_active_user, require_edition_for_mode from app.api.deps import get_current_active_user, require_edition_for_mode
from app.schemas.conversation import MessageCreate, ConversationDocOut, CreatedId, MessageSendResult from app.schemas.conversation import (
from app.services.conversation import create_conversation, get_conversation, add_message, get_user_conversations MessageCreate,
ConversationDocOut,
ConversationResponse,
CreatedId,
MessageSendResult,
DeleteResult,
)
from app.services.conversation import (
create_conversation,
get_conversation,
add_message,
get_user_conversations,
delete_conversation,
)
# 在路由层挂载版别运行模式依赖,限制仅允许当前模式的用户访问 # 在路由层挂载版别运行模式依赖,限制仅允许当前模式的用户访问
router = APIRouter(dependencies=[Depends(require_edition_for_mode())]) router = APIRouter(dependencies=[Depends(require_edition_for_mode())])
@router.post("/", status_code=status.HTTP_201_CREATED, response_model=CreatedId) @router.post("/", status_code=status.HTTP_201_CREATED, response_model=CreatedId)
async def create_new_conversation(current_user: dict = Depends(get_current_active_user)): async def create_new_conversation(current_user: dict = Depends(get_current_active_user)):
"""创建新对话""" """创建新对话(返回新建 ID)
用途:为当前用户新建会话,并返回新会话的 ID。
依赖:鉴权用户、版别运行模式。
"""
conversation_id = await create_conversation(str(current_user["_id"])) conversation_id = await create_conversation(str(current_user["_id"]))
return {"id": conversation_id} return {"id": conversation_id}
@router.get("/", response_model=List[ConversationDocOut]) @router.get("/", response_model=List[ConversationResponse])
async def list_conversations(current_user: dict = Depends(get_current_active_user)): async def list_conversations(current_user: dict = Depends(get_current_active_user)):
"""获取用户的所有对话""" """获取用户的所有对话(列表优化)
用途:返回当前用户的对话列表,统一字段并降低负载(仅最近一条消息)。
"""
conversations = await get_user_conversations(str(current_user["_id"])) conversations = await get_user_conversations(str(current_user["_id"]))
return conversations return conversations
...@@ -24,7 +42,9 @@ async def get_single_conversation( ...@@ -24,7 +42,9 @@ async def get_single_conversation(
conversation_id: str, conversation_id: str,
current_user: dict = Depends(get_current_active_user) current_user: dict = Depends(get_current_active_user)
): ):
"""获取单个对话""" """获取单个对话详情
用途:返回指定对话的完整消息列表,统一 ID 与标题字段。
"""
conversation = await get_conversation(conversation_id, str(current_user["_id"])) conversation = await get_conversation(conversation_id, str(current_user["_id"]))
if not conversation: if not conversation:
raise HTTPException( raise HTTPException(
...@@ -33,13 +53,29 @@ async def get_single_conversation( ...@@ -33,13 +53,29 @@ async def get_single_conversation(
) )
return conversation return conversation
@router.delete("/{conversation_id}", response_model=DeleteResult)
async def remove_conversation(
conversation_id: str,
current_user: dict = Depends(get_current_active_user)
):
"""删除对话
用途:仅允许删除当前用户归属的对话,并清理关联敏感记录。
返回:删除结果(deleted: bool)
"""
ok = await delete_conversation(conversation_id, str(current_user["_id"]))
if not ok:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="对话不存在或无权限")
return {"deleted": True, "message": "删除成功"}
@router.post("/{conversation_id}/messages", response_model=MessageSendResult) @router.post("/{conversation_id}/messages", response_model=MessageSendResult)
async def send_message( async def send_message(
conversation_id: str, conversation_id: str,
message: MessageCreate, message: MessageCreate,
current_user: dict = Depends(get_current_active_user) current_user: dict = Depends(get_current_active_user)
): ):
"""发送消息并获取回复""" """发送消息并获取回复
用途:在指定对话中发送用户消息;若命中敏感词返回拒绝回复并记录;否则返回模型生成的助手回复。
"""
# 检查对话是否存在 # 检查对话是否存在
conversation = await get_conversation(conversation_id, str(current_user["_id"])) conversation = await get_conversation(conversation_id, str(current_user["_id"]))
if not conversation: if not conversation:
......
...@@ -2,6 +2,19 @@ from typing import List, Optional ...@@ -2,6 +2,19 @@ from typing import List, Optional
from pydantic import BaseModel from pydantic import BaseModel
from datetime import datetime from datetime import datetime
class SensitiveWordInfoResponse(BaseModel):
"""敏感词信息结构化模型
字段说明:
- word: 敏感词文本
- category: 一级分类
- subcategory: 二级分类
- severity: 严重程度(数值越大越严重)
"""
word: str
category: Optional[str] = None
subcategory: Optional[str] = None
severity: Optional[int] = None
class MessageCreate(BaseModel): class MessageCreate(BaseModel):
content: str content: str
...@@ -10,17 +23,20 @@ class MessageResponse(BaseModel): ...@@ -10,17 +23,20 @@ class MessageResponse(BaseModel):
content: str content: str
timestamp: datetime timestamp: datetime
contains_sensitive_words: bool contains_sensitive_words: bool
sensitive_words_found: List[str] sensitive_words_found: List[SensitiveWordInfoResponse]
class ConversationResponse(BaseModel): class ConversationResponse(BaseModel):
id: str id: str
title: Optional[str] = None
messages: List[MessageResponse] messages: List[MessageResponse]
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
class ConversationDocOut(BaseModel): class ConversationDocOut(BaseModel):
_id: str id: str
_id: Optional[str] = None
user_id: Optional[str] = None user_id: Optional[str] = None
title: Optional[str] = None
messages: List[MessageResponse] messages: List[MessageResponse]
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
...@@ -28,7 +44,11 @@ class ConversationDocOut(BaseModel): ...@@ -28,7 +44,11 @@ class ConversationDocOut(BaseModel):
class CreatedId(BaseModel): class CreatedId(BaseModel):
id: str id: str
class DeleteResult(BaseModel):
deleted: bool
message: Optional[str] = None
class MessageSendResult(BaseModel): class MessageSendResult(BaseModel):
contains_sensitive_words: bool contains_sensitive_words: bool
sensitive_words_found: List[str] sensitive_words_found: List[SensitiveWordInfoResponse]
assistant_response: str assistant_response: str
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment