""" 聊天相关的请求和响应模型 """ from datetime import datetime from typing import Optional, List from pydantic import BaseModel, ConfigDict, Field class ChatRequest(BaseModel): """聊天请求模型 深度思考是否启用仅由数据库 user_list.is_reasoner 决定,请求中不要、也不应携带 use_reasoner。 """ model_config = ConfigDict(extra="forbid") thread_id: str = Field(..., description="会话线程 ID(UUID 格式)") query: str = Field(..., description="用户查询内容", min_length=1) knowledge_base_id: Optional[int] = Field(None, description="知识库 ID(可选)") knowledge_graph_id: Optional[int] = Field(None, description="知识图谱 graphs.id(可选,与知识库二选一)") llm_provider: Optional[str] = Field( "tongyi", description="大模型提供方:tongyi(通义千问)或 deepseek", ) llm_model: Optional[str] = Field( None, description="模型逻辑 id(与 GET /api/chat/llm-options 中 models[].id 一致);省略则使用各端默认", ) text2img: Optional[bool] = Field(False, description="是否使用文生图模式") text2video: Optional[bool] = Field(False, description="是否使用文生视频模式") text2poster: Optional[bool] = Field(False, description="是否使用创意海报生成模式") translate: Optional[bool] = Field(False, description="是否使用翻译模式") from_language: Optional[str] = Field(None, description="源语言(翻译模式使用,如 'auto'、'zh'、'en' 等)") target_language: Optional[str] = Field(None, description="目标语言(翻译模式使用,如 'en'、'zh' 等)") class DeleteThreadRequest(BaseModel): """删除会话请求模型""" thread_id: str = Field(..., description="要删除的会话线程 ID(UUID 格式)") class GenerateTitleRequest(BaseModel): """生成标题请求模型""" thread_id: str = Field(..., description="会话线程 ID(UUID 格式)") query: str = Field(..., description="用户查询内容", min_length=1) class GenerateTitleResponse(BaseModel): """生成标题响应模型""" title: str = Field(..., description="生成的标题") original_query: str = Field(..., description="原始查询内容") class SearchSettingResponse(BaseModel): """联网搜索设置响应模型""" is_search: bool = Field(..., description="是否启用联网搜索") class UpdateSearchSettingRequest(BaseModel): """更新联网搜索设置请求模型""" is_search: bool = Field(..., description="是否启用联网搜索") class ReasonerSettingResponse(BaseModel): """深度思考设置响应模型""" is_reasoner: bool = Field(..., description="是否启用深度思考") class UpdateReasonerSettingRequest(BaseModel): """更新深度思考设置请求模型""" is_reasoner: bool = Field(..., description="是否启用深度思考") class RenameThreadRequest(BaseModel): """重命名会话请求模型""" title: str = Field(..., description="新标题", min_length=1, max_length=50) class ChatThreadItem(BaseModel): """会话列表项模型""" id: int = Field(..., description="会话 ID") thread_id: str = Field(..., description="会话线程 ID") title: str = Field(..., description="会话标题") first_query: str = Field(..., description="首次请求内容") message_count: int = Field(..., description="消息数量") knowledge_base_id: Optional[int] = Field(None, description="绑定的知识库 ID") knowledge_graph_id: Optional[int] = Field(None, description="绑定的知识图谱 ID") created_at: datetime = Field(..., description="创建时间") updated_at: datetime = Field(..., description="最后更新时间") class ChatThreadListResponse(BaseModel): """会话列表响应模型""" total: int = Field(..., description="总记录数") page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") total_pages: int = Field(..., description="总页数") items: list[ChatThreadItem] = Field(..., description="会话列表") class ChatThreadDetailResponse(BaseModel): """会话明细响应模型""" thread_id: str = Field(..., description="会话线程 ID") title: str = Field(..., description="会话标题") knowledge_base_id: Optional[int] = Field(None, description="绑定的知识库 ID") knowledge_graph_id: Optional[int] = Field(None, description="绑定的知识图谱 ID") llm_provider: Optional[str] = Field(None, description="会话最近一次选用的提供方(若库已迁移)") llm_model: Optional[str] = Field(None, description="会话最近一次选用的模型逻辑 id") # message_count: int = Field(..., description="消息数量") messages: List[dict] = Field(..., description="消息列表")