feat(model and app statistic): 1. Optimize the model list; 2. Increase the model combination; 3. Add a model square; 4. Add application management statistics

This commit is contained in:
Timebomb2018
2026-01-28 10:15:51 +08:00
parent bf3e30dac0
commit 2862db3534
14 changed files with 1458 additions and 233 deletions

View File

@@ -1,19 +1,31 @@
import datetime
import uuid
from enum import StrEnum
from typing import Optional, List
from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey, Enum as SQLEnum
from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey, Enum as SQLEnum, UniqueConstraint, Integer, ARRAY, Table
from sqlalchemy.dialects.postgresql import UUID, JSON
from sqlalchemy.orm import relationship
from app.db import Base
class BaseModel(Base):
"""基础模型(抽象类,提取公共字段)"""
__abstract__ = True # 标记为抽象类,不生成表
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
created_at = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
is_active = Column(Boolean, default=True, nullable=False, comment="是否激活")
class ModelType(StrEnum):
"""模型类型枚举"""
LLM = "llm"
CHAT = "chat"
EMBEDDING = "embedding"
RERANK = "rerank"
# IMAGE = "image"
# AUDIO = "audio"
# VISION = "vision"
class ModelProvider(StrEnum):
@@ -30,16 +42,37 @@ class ModelProvider(StrEnum):
XINFERENCE = "xinference"
GPUSTACK = "gpustack"
BEDROCK = "bedrock"
COMPOSITE = "composite"
class ModelConfig(Base):
class LoadBalanceStrategy(StrEnum):
"""API Key负载均衡策略枚举"""
ROUND_ROBIN = "round_robin" # 轮询
WEIGHTED_ROUND_ROBIN = "weighted_round_robin" # 加权轮询
RANDOM = "random" # 随机
# 多对多关联表
model_config_api_key_association = Table(
'model_config_api_key_association',
Base.metadata,
Column('model_config_id', UUID(as_uuid=True), ForeignKey('model_configs.id'), primary_key=True),
Column('api_key_id', UUID(as_uuid=True), ForeignKey('model_api_keys.id'), primary_key=True),
Column('created_at', DateTime, default=datetime.datetime.now)
)
class ModelConfig(BaseModel):
"""模型配置表"""
__tablename__ = "model_configs"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
model_id = Column(UUID(as_uuid=True), ForeignKey("model_bases.id"), nullable=True, index=True, comment="基础模型ID")
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id"), nullable=False, index=True, comment="租户ID")
logo = Column(String(255), nullable=True, comment="模型logo图片URL")
name = Column(String, nullable=False, comment="模型显示名称")
provider = Column(String, nullable=False, comment="供应商", server_default=ModelProvider.COMPOSITE)
type = Column(String, nullable=False, index=True, comment="模型类型")
is_composite = Column(Boolean, default=False, server_default="true", nullable=False, comment="是否为组合模型")
description = Column(String, comment="模型描述")
# 模型配置参数
@@ -56,29 +89,28 @@ class ModelConfig(Base):
# context_length = Column(String, comment="上下文长度")
# 状态管理
is_active = Column(Boolean, default=True, nullable=False, comment="是否激活")
is_public = Column(Boolean, default=False, nullable=False, comment="是否公开")
# 时间戳
created_at = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
load_balance_strategy = Column(String, nullable=True, comment="负载均衡策略")
# 关联关系
api_keys = relationship("ModelApiKey", back_populates="model_config", cascade="all, delete-orphan")
model_base = relationship("ModelBase", back_populates="configs")
api_keys = relationship(
"ModelApiKey",
secondary=model_config_api_key_association,
back_populates="model_configs"
)
def __repr__(self):
return f"<ModelConfig(id={self.id}, name={self.name}, type={self.type})>"
class ModelApiKey(Base):
class ModelApiKey(BaseModel):
"""模型API密钥表"""
__tablename__ = "model_api_keys"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
model_config_id = Column(UUID(as_uuid=True), ForeignKey("model_configs.id"), nullable=False, comment="模型配置ID")
# API Key 信息
model_name = Column(String, nullable=False, comment="模型实际名称")
description = Column(String, comment="备注")
provider = Column(String, nullable=False, comment="API Key提供商")
api_key = Column(String, nullable=False, comment="API密钥")
api_base = Column(String, comment="API基础URL")
@@ -91,15 +123,41 @@ class ModelApiKey(Base):
last_used_at = Column(DateTime, comment="最后使用时间")
# 状态管理
is_active = Column(Boolean, default=True, nullable=False, comment="是否激活")
priority = Column(String, default="1", comment="优先级")
# 时间戳
created_at = Column(DateTime, default=datetime.datetime.now, comment="创建时间")
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="更新时间")
# 关联关系
model_config = relationship("ModelConfig", back_populates="api_keys")
model_configs = relationship(
"ModelConfig",
secondary=model_config_api_key_association,
back_populates="api_keys"
)
def __repr__(self):
return f"<ModelApiKey(id={self.id}, model_name={self.model_name}, provider={self.provider}, model_config_id={self.model_config_id})>"
return f"<ModelApiKey(id={self.id}, model_name={self.model_name}, provider={self.provider})>"
class ModelBase(Base):
"""基础模型信息表(模型广场)"""
__tablename__ = "model_bases"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
logo = Column(String(255), nullable=True, comment="模型logo图片URL")
name = Column(String, nullable=False, comment="模型唯一标识如gpt-3.5-turbo")
type = Column(String, nullable=False, index=True, comment="模型类型")
provider = Column(String, nullable=False, index=True)
description = Column(Text, comment="模型描述")
is_deprecated = Column(Boolean, default=False, nullable=False, comment="是否弃用")
is_official = Column(Boolean, default=True, comment="是否供应商官方模型(区分自定义)")
tags = Column(ARRAY(String), default=[], nullable=False, comment="模型标签(如['聊天', '创作']")
add_count = Column(Integer, default=0, nullable=False, comment="模型被用户添加的次数")
# 关联关系
configs = relationship("ModelConfig", back_populates="model_base", cascade="all, delete-orphan")
__table_args__ = (
UniqueConstraint("name", "provider", name="uk_model_name_provider"),
)
def __repr__(self):
return f"<ModelBase(name={self.name}, provider={self.provider}, type={self.type})>"