Files
FastapiAdmin/backend/app/plugin/module_application/ai/schema.py
T
zhangtao 45dad1e256 feat(ai): 新增智能助手功能模块
feat(backend): 添加ChromaDB向量数据库支持
feat(backend): 实现智能体配置、知识库和文档管理
feat(backend): 重构WebSocket聊天服务为AgentService
feat(frontend): 实现完整的聊天界面组件
feat(frontend): 添加智能体配置、知识库和文档管理页面
fix(user): 修复用户导入时性别转换问题
style(import): 优化导入组件加载状态处理
2026-02-09 01:22:48 +08:00

217 lines
9.3 KiB
Python

from fastapi import Query
from pydantic import BaseModel, ConfigDict, Field
from app.common.enums import QueueEnum
from app.core.base_schema import BaseSchema, UserBySchema
from app.core.validator import DateTimeStr
class ChatQuerySchema(BaseModel):
"""聊天查询模型"""
message: str = Field(..., min_length=1, max_length=4000, description="聊天消息")
knowledge_ids: list[int] | None = Field(None, description="知识库ID列表,用于RAG检索")
agent_config_id: int | None = Field(None, description="智能体配置ID,用于指定使用的智能体配置")
class AgentConfigSchema(BaseModel):
"""智能体配置参数"""
provider: str = Field("openai", description="LLM 供应商")
model: str = Field(..., description="LLM 名称")
api_key: str = Field(..., description="LLM API Key")
base_url: str | None = Field(None, description="自定义 LLM API 地址")
temperature: float = Field(0.7, description="温度参数,控制随机性")
system_prompt: str = Field("你是一个有用的AI助手,可以帮助用户回答问题和提供帮助。请用中文回答用户的问题。", description="系统提示词")
class AgentConfigCreateSchema(BaseModel):
"""创建智能体配置参数"""
name: str = Field(..., max_length=100, description="智能体名称")
provider: str = Field("openai", max_length=50, description="LLM 供应商")
model: str = Field(..., max_length=100, description="LLM 名称")
api_key: str = Field(..., max_length=500, description="LLM API Key")
base_url: str | None = Field(None, max_length=500, description="自定义 LLM API 地址")
temperature: float = Field(0.7, ge=0.0, le=2.0, description="温度参数,控制随机性")
system_prompt: str = Field(
"你是一个有用的AI助手,可以帮助用户回答问题和提供帮助。请用中文回答用户的问题。",
description="系统提示词",
)
is_default: bool = Field(False, description="是否默认配置")
is_active: bool = Field(True, description="是否启用")
class AgentConfigUpdateSchema(BaseModel):
"""更新智能体配置参数"""
name: str | None = Field(None, max_length=100, description="智能体名称")
provider: str | None = Field(None, max_length=50, description="LLM 供应商")
model: str | None = Field(None, max_length=100, description="LLM 名称")
api_key: str | None = Field(None, max_length=500, description="LLM API Key")
base_url: str | None = Field(None, max_length=500, description="自定义 LLM API 地址")
temperature: float | None = Field(None, ge=0.0, le=2.0, description="温度参数,控制随机性")
system_prompt: str | None = Field(None, description="系统提示词")
is_default: bool | None = Field(None, description="是否默认配置")
is_active: bool | None = Field(None, description="是否启用")
class AgentConfigOutSchema(AgentConfigCreateSchema, BaseSchema, UserBySchema):
"""智能体配置详情"""
model_config = ConfigDict(from_attributes=True)
class AgentConfigQueryParam:
"""智能体配置查询参数"""
def __init__(
self,
name: str | None = Query(None, description="智能体名称"),
provider: str | None = Query(None, description="LLM 供应商"),
is_default: bool | None = Query(None, description="是否默认配置"),
is_active: bool | None = Query(None, description="是否启用"),
created_time: list[DateTimeStr] | None = Query(
None,
description="创建时间范围",
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
),
updated_time: list[DateTimeStr] | None = Query(
None,
description="更新时间范围",
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
),
created_id: int | None = Query(None, description="创建人"),
updated_id: int | None = Query(None, description="更新人"),
) -> None:
self.name = (QueueEnum.like.value, name)
self.provider = (QueueEnum.eq.value, provider)
self.is_default = (QueueEnum.eq.value, is_default)
self.is_active = (QueueEnum.eq.value, is_active)
self.created_id = (QueueEnum.eq.value, created_id)
self.updated_id = (QueueEnum.eq.value, updated_id)
if created_time and len(created_time) == 2:
self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
if updated_time and len(updated_time) == 2:
self.updated_time = (QueueEnum.between.value, (updated_time[0], updated_time[1]))
class KnowledgeCreateSchema(BaseModel):
"""创建知识库参数"""
name: str = Field(..., max_length=100, description="知识库名称")
description: str | None = Field(None, max_length=500, description="知识库描述")
embedding_model: str = Field("openai", max_length=100, description="嵌入模型")
chunk_size: int = Field(500, ge=100, le=2000, description="分块大小")
chunk_overlap: int = Field(50, ge=0, le=500, description="分块重叠大小")
is_active: bool = Field(True, description="是否启用")
class KnowledgeUpdateSchema(KnowledgeCreateSchema):
"""更新知识库参数"""
class KnowledgeOutSchema(KnowledgeCreateSchema, BaseSchema, UserBySchema):
"""知识库详情"""
model_config = ConfigDict(from_attributes=True)
class KnowledgeQueryParam:
"""知识库查询参数"""
def __init__(
self,
name: str | None = Query(None, description="知识库名称"),
is_active: bool | None = Query(None, description="是否启用"),
created_time: list[DateTimeStr] | None = Query(
None,
description="创建时间范围",
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
),
updated_time: list[DateTimeStr] | None = Query(
None,
description="更新时间范围",
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
),
created_id: int | None = Query(None, description="创建人"),
updated_id: int | None = Query(None, description="更新人"),
) -> None:
self.name = (QueueEnum.like.value, name)
self.is_active = (QueueEnum.eq.value, is_active)
self.created_id = (QueueEnum.eq.value, created_id)
self.updated_id = (QueueEnum.eq.value, updated_id)
if created_time and len(created_time) == 2:
self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
if updated_time and len(updated_time) == 2:
self.updated_time = (QueueEnum.between.value, (updated_time[0], updated_time[1]))
class KnowledgeDocumentCreateSchema(BaseModel):
"""创建知识库文档参数"""
knowledge_id: int = Field(..., description="知识库ID")
title: str = Field(..., max_length=200, description="文档标题")
content: str = Field(..., description="文档内容")
file_type: str = Field("text", max_length=50, description="文件类型")
file_path: str | None = Field(None, max_length=500, description="文件路径")
meta_data: dict[str, str] | None = Field(None, description="元数据")
class KnowledgeDocumentUpdateSchema(BaseModel):
"""更新知识库文档参数"""
title: str | None = Field(None, max_length=200, description="文档标题")
content: str | None = Field(None, description="文档内容")
meta_data: dict[str, str] | None = Field(None, description="元数据")
chunk_count: int | None = Field(None, description="分块数量")
is_indexed: bool | None = Field(None, description="是否已索引")
model_config = ConfigDict(extra="allow")
class KnowledgeDocumentOutSchema(KnowledgeDocumentCreateSchema, BaseSchema, UserBySchema):
"""知识库文档详情"""
chunk_count: int = Field(..., description="分块数量")
is_indexed: bool = Field(..., description="是否已索引")
model_config = ConfigDict(from_attributes=True)
class KnowledgeDocumentQueryParam:
"""知识库文档查询参数"""
def __init__(
self,
knowledge_id: int | None = Query(None, description="知识库ID"),
title: str | None = Query(None, description="文档标题"),
file_type: str | None = Query(None, description="文件类型"),
is_indexed: bool | None = Query(None, description="是否已索引"),
created_time: list[DateTimeStr] | None = Query(
None,
description="创建时间范围",
examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
),
created_id: int | None = Query(None, description="创建人"),
) -> None:
self.knowledge_id = (QueueEnum.eq.value, knowledge_id)
self.title = (QueueEnum.like.value, title)
self.file_type = (QueueEnum.eq.value, file_type)
self.is_indexed = (QueueEnum.eq.value, is_indexed)
self.created_id = (QueueEnum.eq.value, created_id)
if created_time and len(created_time) == 2:
self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
class RAGQuerySchema(BaseModel):
"""RAG检索查询参数"""
query: str = Field(..., description="检索查询")
knowledge_ids: list[int] = Field(..., description="知识库ID列表")
top_k: int = Field(3, ge=1, le=10, description="返回最相关的文档数量")