Files
ai-video-fullstack/backend/schemas.py
Xin Wang b444ea777c Implement knowledge base management and enhance assistant configuration
Add CRUD functionality for knowledge bases, including routes for listing, creating, updating, and deleting knowledge bases. Update the assistant model to include foreign key references to knowledge bases and modify the assistant configuration to handle external API keys securely. Refactor related services and routes to accommodate these changes, ensuring proper handling of credential resolution and configuration normalization.
2026-06-09 08:31:39 +08:00

134 lines
3.9 KiB
Python

"""面向前端的请求/响应 DTO。与 DB 模型解耦,**响应里的 key 一律打码**。
凭证 DTO 字段对齐前端 ComponentsModelsPage 的 ModelResource:
JSON 用 camelCase(modelId/interfaceType/apiUrl/apiKey),Python 内部用 snake_case,
靠 Pydantic alias 自动互转。FastAPI 响应默认 by_alias=True,所以出参也是 camelCase。
"""
from __future__ import annotations
from typing import Any, Literal
from pydantic import BaseModel, ConfigDict, model_validator
from pydantic.alias_generators import to_camel
RuntimeMode = Literal["pipeline", "realtime"]
ModelType = Literal["LLM", "ASR", "TTS", "Realtime", "Embedding"]
InterfaceType = Literal["openai", "xfyun", "dashscope", "gemini"]
AssistantType = Literal["prompt", "workflow", "dify", "fastgpt", "opencode"]
# 外部应用类型:其 config.apiKey 是该助手私有密钥,读时打码 / 写时哨兵
EXTERNAL_TYPES = {"dify", "fastgpt", "opencode"}
class CamelModel(BaseModel):
"""JSON camelCase ↔ Python snake_case。protected_namespaces 关掉以允许 model_id。"""
model_config = ConfigDict(
alias_generator=to_camel,
populate_by_name=True,
protected_namespaces=(),
)
# ---------- 各类型的 config 形态(JSON 内嵌,按 type 校验) ----------
class PromptConfig(CamelModel):
prompt: str = ""
realtime_model: str = ""
class WorkflowConfig(CamelModel):
graph: dict[str, Any] = {} # {nodes, edges, viewport};节点 data 可带 *CredentialId 覆盖
class DifyConfig(CamelModel):
api_url: str = ""
api_key: str = "" # 写时:占位符/空 → 保留旧
class FastgptConfig(CamelModel):
app_id: str = ""
api_url: str = ""
api_key: str = ""
class OpencodeConfig(CamelModel):
prompt: str = ""
api_url: str = ""
api_key: str = ""
CONFIG_BY_TYPE: dict[str, type[CamelModel]] = {
"prompt": PromptConfig,
"workflow": WorkflowConfig,
"dify": DifyConfig,
"fastgpt": FastgptConfig,
"opencode": OpencodeConfig,
}
# ---------- 助手(单表,无版本化;type 可变) ----------
class AssistantUpsert(CamelModel):
name: str
type: AssistantType = "prompt"
runtime_mode: RuntimeMode = "pipeline"
greeting: str = ""
enable_interrupt: bool = True
# 引用注册资源(FK id;None=未选)
llm_credential_id: str | None = None
asr_credential_id: str | None = None
tts_credential_id: str | None = None
realtime_credential_id: str | None = None
knowledge_base_id: str | None = None
# 类型专属字段;校验后归一为 camelCase 存库
config: dict[str, Any] = {}
@model_validator(mode="after")
def _normalize_config(self):
model = CONFIG_BY_TYPE[self.type]
# 按当前 type 校验并裁掉无关字段,统一回 camelCase 落库
self.config = model.model_validate(self.config).model_dump(by_alias=True)
return self
class AssistantOut(AssistantUpsert):
id: str
updated_at: str | None = None
# ---------- 知识库 ----------
class KnowledgeBaseUpsert(CamelModel):
name: str
description: str = ""
embedding_credential_id: str | None = None
class KnowledgeBaseOut(KnowledgeBaseUpsert):
id: str
status: str = "active"
updated_at: str | None = None
# ---------- 模型凭证(对齐前端 ModelResource) ----------
class CredentialUpsert(CamelModel):
name: str = "" # 资源名称
model_id: str = "" # 模型ID
type: ModelType # LLM/ASR/TTS/Realtime/Embedding
interface_type: InterfaceType = "openai" # openai/xfyun/dashscope/gemini
api_url: str = ""
api_key: str = "" # 写时:占位符/空表示不改
is_default: bool = False
class CredentialOut(CamelModel):
id: str
name: str
model_id: str
type: str
interface_type: str
api_url: str
api_key: str # 读时:打码后的值
is_default: bool