252 lines
11 KiB
Go
252 lines
11 KiB
Go
// Filename: internal/models/models.go
|
||
package models
|
||
|
||
import (
|
||
"time"
|
||
|
||
"gorm.io/datatypes"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// ========= 自定义类型和常量 =========
|
||
type APIKeyStatus string
|
||
type MasterAPIKeyStatus string
|
||
type PollingStrategy string
|
||
type FileProcessingState string
|
||
type LogType string
|
||
type ProtocolType string
|
||
|
||
const (
|
||
// --- 运营状态 (在中间表中使用) ---
|
||
StatusPendingValidation APIKeyStatus = "PENDING_VALIDATION"
|
||
StatusActive APIKeyStatus = "ACTIVE"
|
||
StatusCooldown APIKeyStatus = "COOLDOWN"
|
||
StatusDisabled APIKeyStatus = "DISABLED"
|
||
StatusBanned APIKeyStatus = "BANNED"
|
||
|
||
// --- 身份状态 (在APIKey实体中使用) ---
|
||
MasterStatusActive MasterAPIKeyStatus = "ACTIVE" // 有效
|
||
MasterStatusRevoked MasterAPIKeyStatus = "REVOKED" // 永久吊销
|
||
MasterStatusManuallyDisabled MasterAPIKeyStatus = "MANUALLY_DISABLED" // 手动全局禁用
|
||
|
||
StrategyWeighted PollingStrategy = "weighted"
|
||
StrategySequential PollingStrategy = "sequential"
|
||
StrategyRandom PollingStrategy = "random"
|
||
FileProcessing FileProcessingState = "PROCESSING"
|
||
FileActive FileProcessingState = "ACTIVE"
|
||
FileFailed FileProcessingState = "FAILED"
|
||
|
||
LogTypeFinal LogType = "FINAL" // Represents the final outcome of a request, including all retries.
|
||
LogTypeRetry LogType = "RETRY" // Represents a single, failed attempt that triggered a retry.
|
||
LogTypeValidation LogType = "VALIDATION"
|
||
|
||
ProtocolOpenAI ProtocolType = "openai"
|
||
ProtocolGemini ProtocolType = "gemini"
|
||
)
|
||
|
||
// ========= 核心数据库模型 =========
|
||
type KeyGroup struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
Name string `gorm:"type:varchar(100);unique;not null"`
|
||
DisplayName string `gorm:"type:varchar(255)"`
|
||
Description string `gorm:"type:text"`
|
||
PollingStrategy PollingStrategy `gorm:"type:varchar(20);not null;default:sequential"`
|
||
EnableProxy bool `gorm:"not null;default:false"`
|
||
Sort int `gorm:"default:0"` // 用于业务逻辑排序 (保留)
|
||
Order int `gorm:"default:0"` // 专用于UI拖拽排序
|
||
LastValidatedAt *time.Time
|
||
Mappings []*GroupAPIKeyMapping `gorm:"foreignKey:KeyGroupID"`
|
||
AllowedModels []*GroupModelMapping `gorm:"foreignKey:GroupID"`
|
||
AllowedUpstreams []*UpstreamEndpoint `gorm:"many2many:group_upstream_access;"`
|
||
ChannelType string `gorm:"type:varchar(50);not null;default:'gemini'"`
|
||
Settings *GroupSettings `gorm:"foreignKey:GroupID"`
|
||
RequestConfigID *uint `json:"request_config_id"`
|
||
RequestConfig *RequestConfig `gorm:"foreignKey:RequestConfigID"`
|
||
}
|
||
|
||
type APIKey struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||
EncryptedKey string `gorm:"type:text;not null"`
|
||
APIKeyHash string `gorm:"type:varchar(64);unique;not null;index"`
|
||
MaskedKey string `gorm:"type:varchar(50);index"`
|
||
MasterStatus MasterAPIKeyStatus `gorm:"type:varchar(25);not null;default:ACTIVE;index"`
|
||
ProxyID *uint `gorm:"index"`
|
||
Mappings []*GroupAPIKeyMapping `gorm:"foreignKey:APIKeyID"`
|
||
APIKey string `gorm:"-"`
|
||
}
|
||
|
||
// GroupAPIKeyMapping 承载 “运营状态”
|
||
type GroupAPIKeyMapping struct {
|
||
KeyGroupID uint `gorm:"primaryKey"`
|
||
APIKeyID uint `gorm:"primaryKey"`
|
||
Status APIKeyStatus `gorm:"type:varchar(25);not null;default:PENDING_VALIDATION;index"`
|
||
LastError string `gorm:"type:text"`
|
||
ConsecutiveErrorCount int `gorm:"not null;default:0"`
|
||
LastUsedAt *time.Time
|
||
CooldownUntil *time.Time
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
APIKey *APIKey `gorm:"foreignKey:APIKeyID"`
|
||
KeyGroup *KeyGroup `gorm:"foreignKey:KeyGroupID"`
|
||
}
|
||
|
||
type RequestLog struct {
|
||
ID uint `gorm:"primarykey"`
|
||
RequestTime time.Time `gorm:"index"`
|
||
LatencyMs int
|
||
IsSuccess bool
|
||
StatusCode int
|
||
ModelName string `gorm:"type:varchar(100);index"`
|
||
GroupID *uint `gorm:"index"`
|
||
KeyID *uint `gorm:"index"`
|
||
AuthTokenID *uint
|
||
UpstreamID *uint
|
||
ProxyID *uint
|
||
Retries int `gorm:"not null;default:0"`
|
||
ErrorCode string `gorm:"type:varchar(50);index"`
|
||
ErrorMessage string `gorm:"type:text"`
|
||
RequestPath string `gorm:"type:varchar(500)"`
|
||
UserAgent string `gorm:"type:varchar(512)"`
|
||
PromptTokens int `gorm:"not null;default:0"`
|
||
CompletionTokens int `gorm:"not null;default:0"`
|
||
CorrelationID string `gorm:"type:varchar(36);index"`
|
||
LogType LogType `gorm:"type:varchar(20);index"`
|
||
Metadata datatypes.JSONMap `gorm:"type:json"`
|
||
}
|
||
|
||
// GroupModelMapping 模型关系表
|
||
type GroupModelMapping struct {
|
||
ID uint `gorm:"primarykey"`
|
||
GroupID uint `gorm:"index;uniqueIndex:idx_group_model_unique"`
|
||
ModelName string `gorm:"type:varchar(100);not null;uniqueIndex:idx_group_model_unique"`
|
||
}
|
||
|
||
// AuthToken
|
||
type AuthToken struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
EncryptedToken string `gorm:"type:text;not null"`
|
||
TokenHash string `gorm:"type:varchar(64);unique;not null;index"`
|
||
Token string `gorm:"-"`
|
||
Description string `gorm:"type:text"`
|
||
Tag string `gorm:"type:varchar(100);index"`
|
||
IsAdmin bool `gorm:"not null;default:false"`
|
||
HasUnrestrictedAccess bool `gorm:"not null;default:false"`
|
||
Status string `gorm:"type:varchar(20);not null;default:active"`
|
||
AllowedGroups []*KeyGroup `gorm:"many2many:token_group_access;"`
|
||
}
|
||
|
||
// FileRecord
|
||
type FileRecord struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
KeyID uint `gorm:"not null"`
|
||
Name string `gorm:"type:varchar(255);unique;not null"`
|
||
DisplayName string `gorm:"type:varchar(255)"`
|
||
MimeType string `gorm:"type:varchar(100);not null"`
|
||
SizeBytes int64 `gorm:"not null"`
|
||
Sha256Hash string `gorm:"type:varchar(64)"`
|
||
State FileProcessingState `gorm:"type:varchar(20);not null;default:PROCESSING"`
|
||
Uri string `gorm:"type:varchar(500);not null"`
|
||
ExpirationTime time.Time `gorm:"not null"`
|
||
}
|
||
|
||
// StatsHourly 长期历史数据仓库,为趋势分析提供高效查询
|
||
type StatsHourly struct {
|
||
ID uint `gorm:"primarykey"`
|
||
Time time.Time `gorm:"uniqueIndex:idx_stats_hourly_unique"`
|
||
GroupID uint `gorm:"uniqueIndex:idx_stats_hourly_unique"`
|
||
ModelName string `gorm:"type:varchar(100);uniqueIndex:idx_stats_hourly_unique"`
|
||
RequestCount int64 `gorm:"not null;default:0"`
|
||
SuccessCount int64 `gorm:"not null;default:0"`
|
||
PromptTokens int64 `gorm:"not null;default:0"`
|
||
CompletionTokens int64 `gorm:"not null;default:0"`
|
||
}
|
||
|
||
type UpstreamEndpoint struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
URL string `gorm:"type:varchar(500);unique;not null"`
|
||
Weight int `gorm:"not null;default:100;index"`
|
||
Status string `gorm:"type:varchar(20);not null;default:'active';index"`
|
||
Description string `gorm:"type:text"`
|
||
}
|
||
type ProxyConfig struct {
|
||
ID uint `gorm:"primarykey"`
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
Address string `gorm:"type:varchar(255);unique;not null"`
|
||
Protocol string `gorm:"type:varchar(10);not null"`
|
||
Status string `gorm:"type:varchar(20);not null;default:'active';index"`
|
||
AssignedKeysCount int `gorm:"not null;default:0;index"`
|
||
Description string `gorm:"type:text"`
|
||
}
|
||
type Setting struct {
|
||
Key string `gorm:"primarykey;type:varchar(100)" json:"key"`
|
||
Value string `gorm:"type:text" json:"value"`
|
||
Name string `gorm:"type:varchar(100)" json:"name"`
|
||
Description string `gorm:"type:varchar(255)" json:"description"`
|
||
Type string `gorm:"type:varchar(20)" json:"type"`
|
||
Category string `gorm:"type:varchar(50);index" json:"category"`
|
||
DefaultValue string `gorm:"type:text" json:"default_value"`
|
||
}
|
||
|
||
// GroupSettings 用于存储特定于Group的配置覆盖
|
||
type GroupSettings struct {
|
||
GroupID uint `gorm:"primaryKey"`
|
||
SettingsJSON datatypes.JSON `gorm:"type:json"` // 将 KeyGroupSettings 序列化后存入此字段
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|
||
|
||
// KeyGroupSettings 定义可以被分组覆盖的所有**运营**配置项
|
||
// 不会直接映射到数据库表,作为 JSON 对象存储在 GroupSettings.SettingsJSON
|
||
type KeyGroupSettings struct {
|
||
// 健康检查相关配置
|
||
EnableKeyCheck *bool `json:"enable_key_check,omitempty"`
|
||
KeyCheckModel *string `json:"key_check_model,omitempty"`
|
||
KeyCheckEndpoint *string `json:"key_check_endpoint,omitempty"`
|
||
KeyCheckConcurrency *int `json:"key_check_concurrency,omitempty"`
|
||
KeyCheckIntervalMinutes *int `json:"key_check_interval_minutes,omitempty"`
|
||
// 惩罚机制相关配置
|
||
KeyBlacklistThreshold *int `json:"key_blacklist_threshold,omitempty"`
|
||
KeyCooldownMinutes *int `json:"key_cooldown_minutes,omitempty"`
|
||
MaxRetries *int `json:"max_retries,omitempty"`
|
||
// Smart Gateway
|
||
EnableSmartGateway *bool `json:"enable_smart_gateway,omitempty"`
|
||
}
|
||
|
||
// RequestConfig 封装了所有直接影响对上游API请求的参数,作为一个独立的数据库模型
|
||
type RequestConfig struct {
|
||
ID uint `gorm:"primarykey"`
|
||
//Custom Headers
|
||
CustomHeaders datatypes.JSONMap `gorm:"type:json" json:"custom_headers"`
|
||
|
||
// Streaming Optimization
|
||
EnableStreamOptimizer bool `json:"enable_stream_optimizer"`
|
||
StreamMinDelay int `json:"stream_min_delay"`
|
||
StreamMaxDelay int `json:"stream_max_delay"`
|
||
StreamShortTextThresh int `json:"stream_short_text_thresh"`
|
||
StreamLongTextThresh int `json:"stream_long_text_thresh"`
|
||
StreamChunkSize int `json:"stream_chunk_size"`
|
||
EnableFakeStream bool `json:"enable_fake_stream"`
|
||
FakeStreamInterval int `json:"fake_stream_interval"`
|
||
|
||
// Model and Safety Settings
|
||
ModelSettings datatypes.JSON `gorm:"type:json" json:"model_settings"`
|
||
|
||
// Generic Overrides for parameters not explicitly defined
|
||
ConfigOverrides datatypes.JSONMap `gorm:"type:json" json:"config_overrides"`
|
||
|
||
CreatedAt time.Time
|
||
UpdatedAt time.Time
|
||
}
|