- Introduce new fields for voice, speed, and language in the AssistantConfig and ProviderCredential models to support TTS and ASR configurations. - Update the database schema and seeding script to accommodate the new fields, ensuring backward compatibility. - Implement credential testing endpoints and logic to validate OpenAI-compatible credentials, enhancing user experience and reliability. - Modify frontend components to include new fields in the credential forms and improve connection testing feedback. - Refactor related services and API interactions to support the new credential testing feature.
113 lines
5.5 KiB
Python
113 lines
5.5 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, Float, 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="") # 明文
|
|
voice: Mapped[str] = mapped_column(String(128), default="") # TTS 音色
|
|
speed: Mapped[float] = mapped_column(Float, default=1.0) # TTS 语速
|
|
language: Mapped[str] = mapped_column(String(32), default="") # ASR 语言
|
|
# 同一 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()
|
|
)
|