provider.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package model
  2. import (
  3. "time"
  4. "github.com/quagmt/udecimal"
  5. "github.com/uptrace/bun"
  6. )
  7. // Provider 供应商模型
  8. type Provider struct {
  9. bun.BaseModel `bun:"table:providers,alias:p"`
  10. ID int `bun:"id,pk,autoincrement" json:"id"`
  11. Name string `bun:"name,notnull" json:"name"`
  12. Description *string `bun:"description" json:"description"`
  13. URL string `bun:"url,notnull" json:"url"`
  14. Key string `bun:"key,notnull" json:"-"` // 不序列化
  15. IsEnabled *bool `bun:"is_enabled,notnull,default:true" json:"isEnabled"`
  16. Weight *int `bun:"weight,notnull,default:1" json:"weight"`
  17. // 优先级和分组配置
  18. Priority *int `bun:"priority,notnull,default:0" json:"priority"`
  19. CostMultiplier *udecimal.Decimal `bun:"cost_multiplier,type:numeric(10,4),default:1.0" json:"costMultiplier"`
  20. GroupTag *string `bun:"group_tag" json:"groupTag"`
  21. // 供应商类型
  22. ProviderType string `bun:"provider_type,notnull,default:'claude'" json:"providerType"` // claude, claude-auth, codex, gemini-cli, gemini, openai-compatible
  23. PreserveClientIp bool `bun:"preserve_client_ip,notnull,default:false" json:"preserveClientIp"`
  24. // 模型重定向
  25. ModelRedirects map[string]string `bun:"model_redirects,type:jsonb" json:"modelRedirects"`
  26. AllowedModels []string `bun:"allowed_models,type:jsonb" json:"allowedModels"`
  27. JoinClaudePool bool `bun:"join_claude_pool,default:false" json:"joinClaudePool"`
  28. // Codex instructions 策略(已废弃但保留兼容)
  29. CodexInstructionsStrategy *string `bun:"codex_instructions_strategy,default:'auto'" json:"codexInstructionsStrategy"` // auto, force_official, keep_original
  30. // MCP 透传配置
  31. McpPassthroughType string `bun:"mcp_passthrough_type,notnull,default:'none'" json:"mcpPassthroughType"` // none, minimax, glm, custom
  32. McpPassthroughUrl *string `bun:"mcp_passthrough_url" json:"mcpPassthroughUrl"`
  33. // 金额限流配置
  34. Limit5hUSD *udecimal.Decimal `bun:"limit_5h_usd,type:numeric(10,2)" json:"limit5hUsd"`
  35. LimitDailyUSD *udecimal.Decimal `bun:"limit_daily_usd,type:numeric(10,2)" json:"limitDailyUsd"`
  36. DailyResetMode string `bun:"daily_reset_mode,notnull,default:'fixed'" json:"dailyResetMode"` // fixed, rolling
  37. DailyResetTime string `bun:"daily_reset_time,notnull,default:'00:00'" json:"dailyResetTime"` // HH:mm 格式
  38. LimitWeeklyUSD *udecimal.Decimal `bun:"limit_weekly_usd,type:numeric(10,2)" json:"limitWeeklyUsd"`
  39. LimitMonthlyUSD *udecimal.Decimal `bun:"limit_monthly_usd,type:numeric(10,2)" json:"limitMonthlyUsd"`
  40. LimitTotalUSD *udecimal.Decimal `bun:"limit_total_usd,type:numeric(10,2)" json:"limitTotalUsd"`
  41. TotalCostResetAt *time.Time `bun:"total_cost_reset_at" json:"totalCostResetAt"`
  42. LimitConcurrentSessions *int `bun:"limit_concurrent_sessions,default:0" json:"limitConcurrentSessions"`
  43. // 熔断器配置
  44. MaxRetryAttempts *int `bun:"max_retry_attempts" json:"maxRetryAttempts"`
  45. CircuitBreakerFailureThreshold *int `bun:"circuit_breaker_failure_threshold,default:5" json:"circuitBreakerFailureThreshold"`
  46. CircuitBreakerOpenDuration *int `bun:"circuit_breaker_open_duration,default:1800000" json:"circuitBreakerOpenDuration"` // ms (30分钟)
  47. CircuitBreakerHalfOpenSuccessThreshold *int `bun:"circuit_breaker_half_open_success_threshold,default:2" json:"circuitBreakerHalfOpenSuccessThreshold"`
  48. // 代理配置
  49. ProxyUrl *string `bun:"proxy_url" json:"proxyUrl"`
  50. ProxyFallbackToDirect bool `bun:"proxy_fallback_to_direct,default:false" json:"proxyFallbackToDirect"`
  51. // 超时配置(毫秒)
  52. FirstByteTimeoutStreamingMs *int `bun:"first_byte_timeout_streaming_ms,notnull,default:0" json:"firstByteTimeoutStreamingMs"`
  53. StreamingIdleTimeoutMs *int `bun:"streaming_idle_timeout_ms,notnull,default:0" json:"streamingIdleTimeoutMs"`
  54. RequestTimeoutNonStreamingMs *int `bun:"request_timeout_non_streaming_ms,notnull,default:0" json:"requestTimeoutNonStreamingMs"`
  55. // 供应商官网
  56. WebsiteUrl *string `bun:"website_url" json:"websiteUrl"`
  57. FaviconUrl *string `bun:"favicon_url" json:"faviconUrl"`
  58. // Cache TTL override
  59. CacheTtlPreference *string `bun:"cache_ttl_preference" json:"cacheTtlPreference"`
  60. // 1M Context Window 偏好配置
  61. Context1mPreference *string `bun:"context_1m_preference" json:"context1mPreference"`
  62. // Codex 参数覆写
  63. CodexReasoningEffortPreference *string `bun:"codex_reasoning_effort_preference" json:"codexReasoningEffortPreference"`
  64. CodexReasoningSummaryPreference *string `bun:"codex_reasoning_summary_preference" json:"codexReasoningSummaryPreference"`
  65. CodexTextVerbosityPreference *string `bun:"codex_text_verbosity_preference" json:"codexTextVerbosityPreference"`
  66. CodexParallelToolCallsPreference *string `bun:"codex_parallel_tool_calls_preference" json:"codexParallelToolCallsPreference"`
  67. // 废弃字段(保留向后兼容)
  68. Tpm *int `bun:"tpm,default:0" json:"tpm"`
  69. Rpm *int `bun:"rpm,default:0" json:"rpm"`
  70. Rpd *int `bun:"rpd,default:0" json:"rpd"`
  71. Cc *int `bun:"cc,default:0" json:"cc"`
  72. CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"`
  73. UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp" json:"updatedAt"`
  74. DeletedAt *time.Time `bun:"deleted_at,soft_delete,nullzero" json:"deletedAt,omitempty"`
  75. }
  76. // SupportsModel 检查供应商是否支持指定模型
  77. func (p *Provider) SupportsModel(model string) bool {
  78. // 如果没有配置允许的模型列表,则支持所有模型
  79. if len(p.AllowedModels) == 0 {
  80. return true
  81. }
  82. for _, m := range p.AllowedModels {
  83. if m == model {
  84. return true
  85. }
  86. }
  87. return false
  88. }
  89. // GetRedirectedModel 获取重定向后的模型名称
  90. func (p *Provider) GetRedirectedModel(model string) string {
  91. if p.ModelRedirects != nil {
  92. if redirected, ok := p.ModelRedirects[model]; ok {
  93. return redirected
  94. }
  95. }
  96. return model
  97. }
  98. // IsActive 检查供应商是否处于活跃状态
  99. func (p *Provider) IsActive() bool {
  100. enabled := true
  101. if p.IsEnabled != nil {
  102. enabled = *p.IsEnabled
  103. }
  104. return enabled && p.DeletedAt == nil
  105. }