- Update Makefile to include new database seed commands for assistants and credentials. - Refactor assistant model to use explicit fields instead of a config dictionary, improving data integrity and clarity. - Implement new seeding SQL script for assistants, ensuring dependencies on credentials are respected. - Modify backend routes and frontend components to accommodate the new assistant structure, including direct field access for prompt, API URL, and keys. - Enhance the AssistantPage component to handle the new data structure and streamline the save process for different assistant types.
110 lines
5.2 KiB
Python
110 lines
5.2 KiB
Python
"""数据表定义(SQLAlchemy 2.0)。
|
|
|
|
两张表,职责分离(见设计):
|
|
- ProviderCredential:模型凭证(key 明文存,同 dograh,靠 DB 访问控制兜底;读时打码)
|
|
- Assistant:助手配置,**只存模型/音色的"选项名",不嵌 key**
|
|
|
|
助手运行时再用 kind 去 ProviderCredential 取真 key(services/config_resolver.py)。
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import JSON, Boolean, DateTime, ForeignKey, String, func
|
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
pass
|
|
|
|
|
|
class ProviderCredential(Base):
|
|
"""模型资源凭证。字段对齐前端 ComponentsModelsPage 的 ModelResource。"""
|
|
|
|
__tablename__ = "provider_credentials"
|
|
|
|
id: Mapped[str] = mapped_column(String(40), primary_key=True) # model_xxx
|
|
name: Mapped[str] = mapped_column(String(128), default="") # 资源名称,如 "DeepSeek-V3"
|
|
model_id: Mapped[str] = mapped_column(String(128), default="") # 模型ID,如 "deepseek-chat"
|
|
type: Mapped[str] = mapped_column(String(16), index=True) # LLM|ASR|TTS|Realtime|Embedding
|
|
interface_type: Mapped[str] = mapped_column(String(32), default="openai") # openai|xfyun|dashscope|gemini
|
|
api_url: Mapped[str] = mapped_column(String(512), default="")
|
|
api_key: Mapped[str] = mapped_column(String(512), default="") # 明文
|
|
# 同一 type 下的默认凭证(后端解析用;前端 ModelResource 无此字段,留作可选)
|
|
is_default: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
|
|
class KnowledgeBase(Base):
|
|
"""知识库注册表。本身引用一个 Embedding 凭证(用哪个向量模型)。
|
|
|
|
文档/分块(pgvector)是 KB 内部实现,这里先不展开;助手侧只认 knowledge_base_id。
|
|
"""
|
|
|
|
__tablename__ = "knowledge_bases"
|
|
|
|
id: Mapped[str] = mapped_column(String(40), primary_key=True) # kb_xxx
|
|
name: Mapped[str] = mapped_column(String(128))
|
|
description: Mapped[str] = mapped_column(String(2048), default="")
|
|
# 该 KB 用哪个向量模型;凭证被删则置空
|
|
embedding_credential_id: Mapped[str | None] = mapped_column(
|
|
String(40),
|
|
ForeignKey("provider_credentials.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
)
|
|
status: Mapped[str] = mapped_column(String(16), default="active") # active|archived
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
|
|
class Assistant(Base):
|
|
"""助手(单表,无版本化)。type 为可变普通列,5 种类型共用此表。
|
|
|
|
模型/KB 以 FK 引用注册表;类型专属字段塞进 config(JSON)。
|
|
"""
|
|
|
|
__tablename__ = "assistants"
|
|
|
|
id: Mapped[str] = mapped_column(String(40), primary_key=True) # asst_xxx
|
|
name: Mapped[str] = mapped_column(String(128))
|
|
# prompt|workflow|dify|fastgpt|opencode;创建后可改
|
|
type: Mapped[str] = mapped_column(String(16), index=True, default="prompt")
|
|
runtime_mode: Mapped[str] = mapped_column(String(16), default="pipeline")
|
|
greeting: Mapped[str] = mapped_column(String(2048), default="")
|
|
enable_interrupt: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
|
|
# ---- 引用"注册好的资源":凭证被删 → SET NULL(resolver 有默认/.env 兜底) ----
|
|
llm_credential_id: Mapped[str | None] = mapped_column(
|
|
String(40), ForeignKey("provider_credentials.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
asr_credential_id: Mapped[str | None] = mapped_column(
|
|
String(40), ForeignKey("provider_credentials.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
tts_credential_id: Mapped[str | None] = mapped_column(
|
|
String(40), ForeignKey("provider_credentials.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
realtime_credential_id: Mapped[str | None] = mapped_column(
|
|
String(40), ForeignKey("provider_credentials.id", ondelete="SET NULL"), nullable=True
|
|
)
|
|
# KB 引用:被引用时禁止删 KB(RESTRICT),无默认兜底
|
|
knowledge_base_id: Mapped[str | None] = mapped_column(
|
|
String(40), ForeignKey("knowledge_bases.id", ondelete="RESTRICT"), nullable=True
|
|
)
|
|
|
|
# ---- 瘦类型专属字段(真列,稀疏:按 type 用其中几列) ----
|
|
prompt: Mapped[str] = mapped_column(String(8192), default="") # prompt / opencode
|
|
api_url: Mapped[str] = mapped_column(String(512), default="") # dify / fastgpt / opencode
|
|
api_key: Mapped[str] = mapped_column(String(512), default="") # dify / fastgpt / opencode(打码/哨兵,同凭证)
|
|
app_id: Mapped[str] = mapped_column(String(128), default="") # fastgpt
|
|
# workflow 专属:图(nodes/edges)。要版本化时再迁出到 assistant_workflow 表
|
|
graph: Mapped[dict] = mapped_column(JSON, default=dict)
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|