New
This commit is contained in:
78
internal/models/dto.go
Normal file
78
internal/models/dto.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// ========= ViewModel / DTOs for Dashboard API =========
|
||||
type StatCard struct {
|
||||
Value float64 `json:"value"`
|
||||
SubValue any `json:"sub_value,omitempty"`
|
||||
SubValueTip string `json:"sub_value_tip,omitempty"`
|
||||
Trend float64 `json:"trend"`
|
||||
TrendIsGrowth bool `json:"trend_is_growth"`
|
||||
}
|
||||
type DashboardStatsResponse struct {
|
||||
KeyCount StatCard `json:"key_count"`
|
||||
RPM StatCard `json:"rpm"`
|
||||
RequestCount24h StatCard `json:"request_count_24h"`
|
||||
ErrorRate24h StatCard `json:"error_rate_24h"`
|
||||
KeyStatusCount map[APIKeyStatus]int64 `json:"key_status_count"`
|
||||
MasterStatusCount map[MasterAPIKeyStatus]int64 `json:"master_status_count"`
|
||||
TokenCount map[string]any `json:"token_count"`
|
||||
UpstreamHealthStatus map[string]string `json:"upstream_health_status,omitempty"`
|
||||
RequestCounts map[string]int64 `json:"request_counts"`
|
||||
}
|
||||
type ChartDataset struct {
|
||||
Label string `json:"label"`
|
||||
Data []int64 `json:"data"`
|
||||
Color string `json:"color"`
|
||||
}
|
||||
type ChartData struct {
|
||||
Labels []string `json:"labels"`
|
||||
Datasets []ChartDataset `json:"datasets"`
|
||||
}
|
||||
|
||||
// TokenUpdateRequest DTO for binding the PUT /admin/tokens request
|
||||
type TokenUpdateRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
Token string `json:"Token"`
|
||||
Description string `json:"Description"`
|
||||
Tag string `json:"Tag"`
|
||||
Status string `json:"Status"`
|
||||
IsAdmin bool `json:"IsAdmin"`
|
||||
AllowedGroupIDs []uint `json:"AllowedGroupIDs"`
|
||||
}
|
||||
|
||||
// 数据传输对象(DTO),表示单个Key的测试结果。
|
||||
// ===================================================================
|
||||
type KeyTestResult struct {
|
||||
Key string `json:"key"`
|
||||
Status string `json:"status"` // "valid", "invalid", "error"
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// APIKeyQueryParams defines the parameters for listing/searching keys.
|
||||
type APIKeyQueryParams struct {
|
||||
KeyGroupID uint `form:"-"`
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"limit"`
|
||||
Status string `form:"status"`
|
||||
Keyword string `form:"keyword"`
|
||||
}
|
||||
|
||||
// APIKeyDetails is a DTO that combines APIKey info with its contextual status from the mapping.
|
||||
type APIKeyDetails struct {
|
||||
// Embedded APIKey fields
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
APIKey string `json:"api_key"`
|
||||
MasterStatus MasterAPIKeyStatus `json:"master_status"`
|
||||
|
||||
// Mapping-specific fields
|
||||
Status APIKeyStatus `json:"status"`
|
||||
LastError string `json:"last_error"`
|
||||
ConsecutiveErrorCount int `json:"consecutive_error_count"`
|
||||
LastUsedAt *time.Time `json:"last_used_at"`
|
||||
CooldownUntil *time.Time `json:"cooldown_until"`
|
||||
EncryptedKey string
|
||||
}
|
||||
69
internal/models/events.go
Normal file
69
internal/models/events.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Filename: internal/models/events.go
|
||||
package models
|
||||
|
||||
import (
|
||||
"gemini-balancer/internal/errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Topic 定义事件总线主题名称
|
||||
const (
|
||||
TopicRequestFinished = "events:request_finished"
|
||||
TopicKeyStatusChanged = "events:key_status_changed"
|
||||
TopicUpstreamHealthChanged = "events:upstream_health_changed"
|
||||
TopicMasterKeyStatusChanged = "master_key_status_changed"
|
||||
TopicImportGroupCompleted = "events:import_group_completed"
|
||||
)
|
||||
|
||||
type RequestFinishedEvent struct {
|
||||
RequestLog
|
||||
KeyID uint
|
||||
GroupID uint
|
||||
IsSuccess bool
|
||||
StatusCode int
|
||||
Error *errors.APIError
|
||||
CorrelationID string `json:"correlation_id,omitempty"`
|
||||
UpstreamID *uint `json:"upstream_id"`
|
||||
UpstreamURL *string `json:"upstream_url,omitempty"`
|
||||
IsPreciseRouting bool `json:"is_precise_routing"`
|
||||
}
|
||||
|
||||
type KeyStatusChangedEvent struct {
|
||||
KeyID uint
|
||||
GroupID uint
|
||||
OldStatus APIKeyStatus
|
||||
NewStatus APIKeyStatus
|
||||
ChangeReason string `json:"change_reason"`
|
||||
ChangedAt time.Time `json:"changed_at"`
|
||||
}
|
||||
|
||||
type UpstreamHealthChangedEvent struct {
|
||||
UpstreamID uint `json:"upstream_id"`
|
||||
UpstreamURL string `json:"upstream_url"`
|
||||
OldStatus string `json:"old_status"` // e.g., "healthy", "unhealthy"
|
||||
NewStatus string `json:"new_status"`
|
||||
Latency time.Duration `json:"latency_ms"` // 延迟时间(毫秒)
|
||||
Reason string `json:"reason"` // 状态变更原因,如 "timeout", "status_503"
|
||||
CheckedAt time.Time `json:"checked_at"`
|
||||
}
|
||||
|
||||
const TopicProxyStatusChanged = "proxy:status_changed"
|
||||
|
||||
type ProxyStatusChangedEvent struct {
|
||||
ProxyID uint `json:"proxy_id"`
|
||||
Action string `json:"action"` // "created", "updated", "deleted"
|
||||
}
|
||||
|
||||
type MasterKeyStatusChangedEvent struct {
|
||||
KeyID uint `json:"key_id"`
|
||||
OldMasterStatus MasterAPIKeyStatus `json:"old_master_status"`
|
||||
NewMasterStatus MasterAPIKeyStatus `json:"new_master_status"`
|
||||
ChangeReason string `json:"change_reason"`
|
||||
ChangedAt time.Time `json:"changed_at"`
|
||||
}
|
||||
|
||||
type ImportGroupCompletedEvent struct {
|
||||
GroupID uint `json:"group_id"`
|
||||
KeyIDs []uint `json:"key_ids"`
|
||||
CompletedAt time.Time `json:"completed_at"`
|
||||
}
|
||||
246
internal/models/models.go
Normal file
246
internal/models/models.go
Normal file
@@ -0,0 +1,246 @@
|
||||
// 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
|
||||
|
||||
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.
|
||||
)
|
||||
|
||||
// ========= 核心数据库模型 =========
|
||||
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
|
||||
}
|
||||
64
internal/models/request.go
Normal file
64
internal/models/request.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Filename: internal/models/request.go
|
||||
package models
|
||||
|
||||
// GeminiRequest 对应客户端发来的JSON请求体
|
||||
type GeminiRequest struct {
|
||||
Contents []GeminiContent `json:"contents"`
|
||||
GenerationConfig GenerationConfig `json:"generationConfig,omitempty"`
|
||||
SafetySettings []SafetySetting `json:"safetySettings,omitempty"`
|
||||
Tools []Tool `json:"tools,omitempty"`
|
||||
}
|
||||
|
||||
// GeminiContent 包含角色和内容部分
|
||||
type GeminiContent struct {
|
||||
Role string `json:"role,omitempty"`
|
||||
Parts []Part `json:"parts"`
|
||||
}
|
||||
|
||||
// Part 代表内容的一个组成部分 (文本或内联数据)
|
||||
type Part struct {
|
||||
Text string `json:"text,omitempty"`
|
||||
InlineData *InlineData `json:"inlineData,omitempty"`
|
||||
}
|
||||
|
||||
// InlineData 用于多模态输入,如图像
|
||||
type InlineData struct {
|
||||
MimeType string `json:"mimeType"`
|
||||
Data string `json:"data"` // Base64-encoded data
|
||||
}
|
||||
|
||||
// GenerationConfig 控制模型的生成行为
|
||||
type GenerationConfig struct {
|
||||
Temperature float32 `json:"temperature,omitempty"`
|
||||
TopP float32 `json:"topP,omitempty"`
|
||||
TopK int `json:"topK,omitempty"`
|
||||
MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
|
||||
StopSequences []string `json:"stopSequences,omitempty"`
|
||||
}
|
||||
|
||||
// SafetySetting 定义安全过滤的阈值
|
||||
type SafetySetting struct {
|
||||
Category string `json:"category"`
|
||||
Threshold string `json:"threshold"`
|
||||
}
|
||||
|
||||
// Tool 定义模型可以调用的外部工具
|
||||
type Tool struct {
|
||||
FunctionDeclarations any `json:"functionDeclarations,omitempty"`
|
||||
}
|
||||
|
||||
// ========= 用于智能网关流式响应解析的模型 =========
|
||||
// GeminiSSEPayload 是用于解析SSE(Server-Sent Events)事件中data字段的结构体
|
||||
// 它代表了从上游接收到的一个数据块。
|
||||
type GeminiSSEPayload struct {
|
||||
Candidates []*Candidate `json:"candidates"`
|
||||
}
|
||||
|
||||
// Candidate 包含了模型生成的内容和会话的结束原因
|
||||
type Candidate struct {
|
||||
// Content 里面包含了本次返回的具体文本内容
|
||||
Content *GeminiContent `json:"content"`
|
||||
// FinishReason 告知我们流结束的原因,例如 "STOP", "MAX_TOKENS" 等。
|
||||
// 这是我们智能重试逻辑判断的核心依据。
|
||||
FinishReason string `json:"finishReason"`
|
||||
}
|
||||
117
internal/models/runtime.go
Normal file
117
internal/models/runtime.go
Normal file
@@ -0,0 +1,117 @@
|
||||
// internal\models\runtime.go
|
||||
package models
|
||||
|
||||
// ========= 运行时配置 (非数据库模型并提供默认值) =========
|
||||
type SystemSettings struct {
|
||||
DefaultUpstreamURL string `json:"default_upstream_url" default:"https://generativelanguage.googleapis.com/v1beta" name:"全局默认上游URL" category:"请求设置" desc:"当密钥组未指定任何专属上游时,将使用此URL作为最终的兜底。"`
|
||||
RequestLogRetentionDays int `json:"request_log_retention_days" default:"7" name:"日志保留天数" category:"基础设置" desc:"请求日志在数据库中的保留天数。"`
|
||||
RequestTimeoutSeconds int `json:"request_timeout_seconds" default:"600" name:"请求超时(秒)" category:"请求设置" desc:"转发请求的完整生命周期超时(秒)。"`
|
||||
ConnectTimeoutSeconds int `json:"connect_timeout_seconds" default:"15" name:"连接超时(秒)" category:"请求设置" desc:"与上游服务建立新连接的超时时间(秒)。"`
|
||||
MaxRetries int `json:"max_retries" default:"3" name:"最大重试次数" category:"请求设置" desc:"单个请求使用不同Key的最大重试次数。"`
|
||||
BlacklistThreshold int `json:"blacklist_threshold" default:"3" name:"拉黑阈值" category:"密钥设置" desc:"一个Key连续失败多少次后进入冷却状态。"`
|
||||
KeyCooldownMinutes int `json:"key_cooldown_minutes" default:"10" name:"密钥冷却时长(分钟)" category:"密钥设置" desc:"一个Key进入冷却状态后需要等待的时间,单位为分钟。"`
|
||||
LogFlushIntervalSeconds int `json:"log_flush_interval_seconds" default:"10" name:"日志刷新间隔(秒)" category:"日志设置" desc:"异步日志写入数据库的间隔时间(秒)。"`
|
||||
|
||||
PollingStrategy PollingStrategy `json:"polling_strategy" default:"random" name:"全局轮询策略" category:"调度设置" desc:"智能聚合模式下,从所有可用密钥中选择一个的默认策略。可选值: sequential(顺序), random(随机), weighted(加权)。"`
|
||||
|
||||
// HealthCheckIntervalSeconds is DEPRECATED. Use specific intervals below.
|
||||
|
||||
UpstreamCheckIntervalSeconds int `json:"upstream_check_interval_seconds" default:"300" name:"上游检查周期(秒)" category:"健康检查" desc:"对所有上游服务进行健康检查的周期。"`
|
||||
ProxyCheckIntervalSeconds int `json:"proxy_check_interval_seconds" default:"600" name:"代理检查周期(秒)" category:"健康检查" desc:"对所有代理服务进行健康检查的周期。"`
|
||||
|
||||
EnableBaseKeyCheck bool `json:"enable_base_key_check" default:"true" name:"启用全局基础Key检查" category:"健康检查" desc:"是否启用全局的、长周期的Key身份状态检查。"`
|
||||
KeyCheckTimeoutSeconds int `json:"key_check_timeout_seconds" default:"20" name:"Key检查超时(秒)" category:"健康检查" desc:"对单个API Key进行有效性验证时的网络超时时间(全局与分组检查共用)。"`
|
||||
BaseKeyCheckIntervalMinutes int `json:"base_key_check_interval_minutes" default:"1440" name:"全局Key检查周期(分钟)" category:"健康检查" desc:"对所有ACTIVE状态的Key进行身份检查的周期,建议设置较长时间,例如1天(1440分钟)。"`
|
||||
BaseKeyCheckConcurrency int `json:"base_key_check_concurrency" default:"5" name:"全局Key检查并发数" category:"健康检查" desc:"执行全局Key身份检查时的并发请求数量。"`
|
||||
BaseKeyCheckEndpoint string `json:"base_key_check_endpoint" default:"https://generativelanguage.googleapis.com/v1beta/models" name:"全局Key检查端点" category:"健康检查" desc:"用于全局Key身份检查的目标URL。"`
|
||||
BaseKeyCheckModel string `json:"base_key_check_model" default:"gemini-1.5-flash" name:"默认Key检查模型" category:"健康检查" desc:"用于分组健康检查和手动密钥测试时的默认回退模型。"`
|
||||
|
||||
EnableUpstreamCheck bool `json:"enable_upstream_check" default:"true" name:"启用上游检查" category:"健康检查" desc:"是否启用对上游服务(Upstream)的健康检查。"`
|
||||
UpstreamCheckTimeoutSeconds int `json:"upstream_check_timeout_seconds" default:"20" name:"上游检查超时(秒)" category:"健康检查" desc:"对单个上游服务进行健康检查时的网络超时时间。"`
|
||||
|
||||
EnableProxyCheck bool `json:"enable_proxy_check" default:"true" name:"启用代理检查" category:"健康检查" desc:"是否启用对代理(Proxy)的健康检查。"`
|
||||
ProxyCheckTimeoutSeconds int `json:"proxy_check_timeout_seconds" default:"20" name:"代理检查超时(秒)" category:"健康检查" desc:"通过代理进行连通性测试时的网络超时时间。"`
|
||||
ProxyCheckConcurrency int `json:"proxy_check_concurrency" default:"5" name:"代理测试并发数" category:"健康检查" desc:"后台手动批量测试代理时的默认并发请求数量。"`
|
||||
UseProxyHash bool `json:"use_proxy_hash" default:"false" name:"是否开启固定代理策略" category:"API配置" desc:"开启后,对于每一个API_KEY将根据算法从代理列表中选取同一个代理IP,防止一个API_KEY同时被多个IP访问,也同时防止了一个IP访问了过多的API_KEY。"`
|
||||
|
||||
AnalyticsFlushIntervalSeconds int `json:"analytics_flush_interval_seconds" default:"60" name:"分析数据落盘间隔(秒)" category:"高级设置" desc:"内存中的统计数据多久写入数据库一次。"`
|
||||
|
||||
// 安全设置
|
||||
EnableIPBanning bool `json:"enable_ip_banning" default:"false" name:"启用IP封禁功能" category:"安全设置" desc:"当一个IP连续多次登录失败后,是否自动将其封禁一段时间。"`
|
||||
MaxLoginAttempts int `json:"max_login_attempts" default:"5" name:"最大登录失败次数" category:"安全设置" desc:"在一个IP被封禁前,允许的连续登录失败次数。"`
|
||||
IPBanDurationMinutes int `json:"ip_ban_duration_minutes" default:"15" name:"IP封禁时长(分钟)" category:"安全设置" desc:"IP被封禁的时长,单位为分钟。"`
|
||||
|
||||
//智能网关
|
||||
LogTruncationLimit int `json:"log_truncation_limit" default:"8000" name:"日志截断长度" category:"日志设置" desc:"在日志中记录上游响应或错误时,保留的最大字符数。0表示不截断。"`
|
||||
EnableSmartGateway bool `json:"enable_smart_gateway" default:"false" name:"启用智能网关" category:"代理设置" desc:"开启后,系统将对流式请求进行智能中断续传、错误标准化等优化。关闭后,系统将作为一个纯净、无干扰的透明代理。"`
|
||||
EnableStreamingRetry bool `json:"enable_streaming_retry" default:"true" name:"启用流式重试" category:"代理设置" desc:"当智能网关开启时,是否对流式请求进行智能中断续传。"`
|
||||
MaxStreamingRetries int `json:"max_streaming_retries" default:"2" name:"最大流式重试次数" category:"代理设置" desc:"对单个流式会话,允许的最大连续重试次数。"`
|
||||
StreamingRetryDelayMs int `json:"streaming_retry_delay_ms" default:"750" name:"流式重试延迟(毫秒)" category:"代理设置" desc:"流式会话重试之间的等待时间,单位为毫秒。"`
|
||||
|
||||
// 智能网关底层HTTP Transport配置
|
||||
TransportMaxIdleConns int `json:"transport_max_idle_conns" default:"200" name:"最大空闲连接数(总)" category:"高级设置" desc:"HTTP客户端Transport的最大总空闲连接数。"`
|
||||
TransportMaxIdleConnsPerHost int `json:"transport_max_idle_conns_per_host" default:"100" name:"最大空-闲连接数(单主机)" category:"高级设置" desc:"HTTP客户端Transport对单个主机的最大空闲连接数。"`
|
||||
TransportIdleConnTimeoutSecs int `json:"transport_idle_conn_timeout_secs" default:"90" name:"空闲连接超时(秒)" category:"高级设置" desc:"HTTP客户端Transport中空闲连接被关闭前的等待时间。"`
|
||||
TransportTLSHandshakeTimeout int `json:"transport_tls_handshake_timeout" default:"10" name:"TLS握手超时(秒)" category:"高级设置" desc:"TLS握手的超时时间。"`
|
||||
|
||||
// 智能续传的自定义Prompt
|
||||
StreamingRetryPrompt string `json:"streaming_retry_prompt" default:"Continue exactly where you left off, providing the final answer without repeating the previous thinking steps." name:"智能续传提示词" category:"代理设置" desc:"在进行智能中断续传时,向模型发送的指令。"`
|
||||
|
||||
// 日志服务相关配置
|
||||
LogLevel string `json:"log_level" default:"INFO" name:"日志级别" category:"日志配置"`
|
||||
AutoDeleteErrorLogsEnabled bool `json:"auto_delete_error_logs_enabled" default:"false" name:"自动删除错误日志" category:"日志配置"`
|
||||
AutoDeleteRequestLogsEnabled bool `json:"auto_delete_request_logs_enabled" default:"false" name:"自动删除请求日志" category:"日志配置"`
|
||||
LogBufferCapacity int `json:"log_buffer_capacity" default:"1000" name:"日志缓冲区容量" category:"日志设置" desc:"内存中日志缓冲区的最大容量,超过则可能丢弃日志。"`
|
||||
LogFlushBatchSize int `json:"log_flush_batch_size" default:"100" name:"日志刷新批次大小" category:"日志设置" desc:"每次向数据库批量写入日志的最大数量。"`
|
||||
|
||||
// --- API配置 ---
|
||||
CustomHeaders map[string]string `json:"custom_headers" name:"自定义Headers" category:"API配置" ` // 默认为nil
|
||||
|
||||
// --- TTS 配置 (模块化预留) ---
|
||||
TTSModel string `json:"tts_model" name:"TTS模型" category:"TTS配置"`
|
||||
TTSVoiceName string `json:"tts_voice_name" name:"TTS语音名称" category:"TTS配置"`
|
||||
TTSSpeed string `json:"tts_speed" name:"TTS语速" category:"TTS配置"`
|
||||
|
||||
// --- 图像生成配置 (模块化预留) ---
|
||||
PaidKey string `json:"paid_key" name:"付费API密钥" category:"图像生成"`
|
||||
CreateImageModel string `json:"create_image_model" name:"图像生成模型" category:"图像生成"`
|
||||
UploadProvider string `json:"upload_provider" name:"上传提供商" category:"图像生成"`
|
||||
SmmsSecretToken string `json:"smms_secret_token" name:"SM.MS密钥" category:"图像生成"`
|
||||
PicgoAPIKey string `json:"picgo_api_key" name:"PicGo API密钥" category:"图像生成"`
|
||||
CloudflareImgbedURL string `json:"cloudflare_imgbed_url" name:"Cloudflare图床URL" category:"图像生成"`
|
||||
CloudflareImgbedAuthCode string `json:"cloudflare_imgbed_auth_code" name:"Cloudflare认证码" category:"图像生成"`
|
||||
CloudflareImgbedUploadFolder string `json:"cloudflare_imgbed_upload_folder" name:"Cloudflare上传文件夹" category:"图像生成"`
|
||||
// --- 流式输出配置 (模块化预留) ---
|
||||
EnableStreamOptimizer bool `json:"enable_stream_optimizer" default:"false" name:"启用流式输出优化" category:"流式输出"`
|
||||
StreamMinDelay int `json:"stream_min_delay" default:"16" name:"最小延迟(秒)" category:"流式输出"`
|
||||
StreamMaxDelay int `json:"stream_max_delay" default:"24" name:"最大延迟(秒)" category:"流式输出"`
|
||||
StreamShortTextThresh int `json:"stream_short_text_thresh" default:"10" name:"短文本阈值" category:"流式输出"`
|
||||
StreamLongTextThresh int `json:"stream_long_text_thresh" default:"50" name:"长文本阈值" category:"流式输出"`
|
||||
StreamChunkSize int `json:"stream_chunk_size" default:"5" name:"分块大小" category:"流式输出"`
|
||||
EnableFakeStream bool `json:"enable_fake_stream" default:"false" name:"启用假流式输出" category:"流式输出"`
|
||||
FakeStreamInterval int `json:"fake_stream_interval" default:"5" name:"假流式空数据发送间隔(秒)" category:"流式输出"`
|
||||
|
||||
// --- 定时任务配置 ---
|
||||
Timezone string `json:"timezone" default:"Asia/Shanghai" name:"时区" category:"定时任务"`
|
||||
|
||||
// --- [短期冻结] 为了UI兼容性而保留的“幻影”字段 ---
|
||||
AllowedTokens []string `json:"-"` // 不参与JSON序列化
|
||||
Proxies []string `json:"-"` // 不参与JSON序列化
|
||||
|
||||
ModelSettings ModelSettings `json:"model_settings" name:"模型配置"`
|
||||
}
|
||||
|
||||
// ModelSettings
|
||||
type ModelSettings struct {
|
||||
ImageModels []string `json:"image_models" name:"图像模型列表"`
|
||||
SearchModels []string `json:"search_models" name:"搜索模型列表"`
|
||||
FilteredModels []string `json:"filtered_models" name:"过滤模型列表"`
|
||||
EnableCodeExecutor bool `json:"enable_code_executor" default:"false" name:"启用代码执行工具"`
|
||||
EnableURLContext bool `json:"enable_url_context" default:"false" name:"启用网址上下文"`
|
||||
URLContextModels []string `json:"url_context_models" name:"网址上下文模型列表"`
|
||||
ShowSearchLink bool `json:"show_search_link" default:"false" name:"显示搜索链接"`
|
||||
ShowThinking bool `json:"show_thinking" default:"false" name:"显示思考过程"`
|
||||
ThinkingModels []string `json:"thinking_models" name:"思考模型列表"`
|
||||
ThinkingBudgetMap map[string]int `json:"thinking_budget_map" name:"思考模型预算映射"`
|
||||
SafetySettings []SafetySetting `json:"safety_settings" name:"安全设置"`
|
||||
}
|
||||
Reference in New Issue
Block a user