Files
dreamweaver/backend/app/db/admin_models.py

127 lines
5.2 KiB
Python

from datetime import datetime, timezone
from decimal import Decimal
from uuid import uuid4
from sqlalchemy import JSON, Boolean, DateTime, ForeignKey, Integer, Numeric, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.db.models import Base
def _uuid() -> str:
return str(uuid4())
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
class Provider(Base):
"""Model provider registry."""
__tablename__ = "providers"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
name: Mapped[str] = mapped_column(String(100), nullable=False)
type: Mapped[str] = mapped_column(String(50), nullable=False) # text/image/tts/storybook/asr
adapter: Mapped[str] = mapped_column(String(100), nullable=False)
model: Mapped[str] = mapped_column(String(200), nullable=True)
api_base: Mapped[str] = mapped_column(String(300), nullable=True)
api_key: Mapped[str] = mapped_column(String(500), nullable=True) # 可选,优先于 config_ref
timeout_ms: Mapped[int] = mapped_column(Integer, default=60000)
max_retries: Mapped[int] = mapped_column(Integer, default=1)
weight: Mapped[int] = mapped_column(Integer, default=1)
priority: Mapped[int] = mapped_column(Integer, default=0)
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
config_json: Mapped[dict | None] = mapped_column(
JSON,
nullable=True,
) # 存储额外配置(speed, vol, etc)
config_ref: Mapped[str] = mapped_column(String(100), nullable=True) # 环境变量 key 名称(回退)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
)
updated_by: Mapped[str] = mapped_column(String(100), nullable=True)
class ProviderMetrics(Base):
"""供应商调用指标记录。"""
__tablename__ = "provider_metrics"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
provider_id: Mapped[str] = mapped_column(
String(36), ForeignKey("providers.id", ondelete="CASCADE"), nullable=False, index=True
)
timestamp: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, index=True
)
success: Mapped[bool] = mapped_column(Boolean, nullable=False)
latency_ms: Mapped[int] = mapped_column(Integer, nullable=True)
cost_usd: Mapped[Decimal] = mapped_column(Numeric(10, 6), nullable=True)
error_message: Mapped[str] = mapped_column(Text, nullable=True)
request_id: Mapped[str] = mapped_column(String(100), nullable=True)
class ProviderHealth(Base):
"""供应商健康状态。"""
__tablename__ = "provider_health"
provider_id: Mapped[str] = mapped_column(
String(36), ForeignKey("providers.id", ondelete="CASCADE"), primary_key=True
)
is_healthy: Mapped[bool] = mapped_column(Boolean, default=True)
last_check: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=True)
consecutive_failures: Mapped[int] = mapped_column(Integer, default=0)
last_error: Mapped[str] = mapped_column(Text, nullable=True)
class ProviderSecret(Base):
"""供应商密钥加密存储。"""
__tablename__ = "provider_secrets"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
encrypted_value: Mapped[str] = mapped_column(Text, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
)
class CostRecord(Base):
"""成本记录表 - 记录每次 API 调用的成本。"""
__tablename__ = "cost_records"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
provider_id: Mapped[str] = mapped_column(String(36), nullable=True) # 可能是环境变量配置
provider_name: Mapped[str] = mapped_column(String(100), nullable=False)
capability: Mapped[str] = mapped_column(String(50), nullable=False)
estimated_cost: Mapped[Decimal] = mapped_column(Numeric(10, 6), nullable=False)
timestamp: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, index=True
)
class UserBudget(Base):
"""用户预算配置。"""
__tablename__ = "user_budgets"
user_id: Mapped[str] = mapped_column(String(36), primary_key=True)
daily_limit_usd: Mapped[Decimal] = mapped_column(Numeric(10, 4), default=Decimal("1.0"))
monthly_limit_usd: Mapped[Decimal] = mapped_column(Numeric(10, 4), default=Decimal("10.0"))
alert_threshold: Mapped[Decimal] = mapped_column(
Numeric(3, 2), default=Decimal("0.8")
) # 80% 时告警
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
)