feat: 优化模型配置管理 - 动态使用优先级最高的Provider

## 主要改进

### 1. 数据库驱动的模型配置
- 新增 GetActiveProviderWithModel() 方法,从数据库获取优先级最高的 Provider 及其默认模型
- 支持多 Provider 配置,通过 priority 字段控制优先级
- 实现 5 分钟缓存机制,减少数据库查询

### 2. 应用模型配置优化
- 移除应用层硬编码模型配置
- 应用自动使用优先级最高的 Provider 的默认模型
- 支持应用级模型覆盖(可选)

### 3. 工具脚本
- check-providers: 查询数据库中的 Provider 和应用配置
- fix-providers: 修复 Provider 配置(补全 config 和 models 字段)
- clear-app-models: 清空应用硬编码模型配置

### 4. 代码质量
- 删除未使用的 getProvider() 方法
- 修复 fmt.Println 冗余换行警告
- 统一代码格式

## 技术细节

**降级策略**:
数据库 Provider (优先级) → 环境变量 Provider → 应用配置模型

**当前配置**:
- 优先级 110: 本地LLM (qwen2.5-7b-instruct)
- 优先级 100: 阿里云百炼 (qwen-plus)

所有 41 个应用现在自动使用本地模型,无需手动配置。
This commit is contained in:
selfrelease
2026-06-22 18:46:44 +08:00
parent 0c1a8544e8
commit 96930b585c
8 changed files with 468 additions and 65 deletions
+23 -10
View File
@@ -116,12 +116,18 @@ func (m *Manager) LoadProvidersFromDB(ctx context.Context) error {
// GetActiveProvider 获取优先级最高的激活 provider
func (m *Manager) GetActiveProvider(ctx context.Context) (Provider, error) {
provider, _, err := m.GetActiveProviderWithModel(ctx)
return provider, err
}
// GetActiveProviderWithModel 获取优先级最高的激活 provider 及其默认模型
func (m *Manager) GetActiveProviderWithModel(ctx context.Context) (Provider, string, error) {
if m.pool == nil {
// 如果没有数据库连接,使用注册的 fallback
if p, ok := m.providers[m.fallback]; ok {
return p, nil
return p, "", nil // 降级时返回空模型名,使用应用配置
}
return nil, fmt.Errorf("no active provider")
return nil, "", fmt.Errorf("no active provider")
}
// 从数据库获取优先级最高的激活 provider
@@ -135,21 +141,25 @@ func (m *Manager) GetActiveProvider(ctx context.Context) (Provider, error) {
LIMIT 1
`).Scan(&id, &baseURL, &apiKey, &configJSON)
if err != nil {
return nil, fmt.Errorf("query active provider: %w", err)
return nil, "", fmt.Errorf("query active provider: %w", err)
}
// 检查缓存
m.cacheMu.RLock()
if entry, ok := m.cache[id]; ok && time.Since(entry.updatedAt) < m.cacheTTL {
m.cacheMu.RUnlock()
return entry.provider, nil
// 从 config 中提取默认模型
var config map[string]any
json.Unmarshal(configJSON, &config)
defaultModel, _ := config["default_model"].(string)
return entry.provider, defaultModel, nil
}
m.cacheMu.RUnlock()
// 创建新的 provider
var config map[string]any
if err := json.Unmarshal(configJSON, &config); err != nil {
return nil, fmt.Errorf("unmarshal config: %w", err)
return nil, "", fmt.Errorf("unmarshal config: %w", err)
}
providerType, _ := config["provider"].(string)
@@ -157,6 +167,9 @@ func (m *Manager) GetActiveProvider(ctx context.Context) (Provider, error) {
providerType = "openai"
}
// 获取默认模型
defaultModel, _ := config["default_model"].(string)
var provider Provider
switch providerType {
case "openai":
@@ -164,7 +177,7 @@ func (m *Manager) GetActiveProvider(ctx context.Context) (Provider, error) {
case "anthropic":
provider = NewAnthropicProvider(apiKey, baseURL, "")
default:
return nil, fmt.Errorf("unsupported provider type: %s", providerType)
return nil, "", fmt.Errorf("unsupported provider type: %s", providerType)
}
// 更新缓存
@@ -175,7 +188,7 @@ func (m *Manager) GetActiveProvider(ctx context.Context) (Provider, error) {
}
m.cacheMu.Unlock()
return provider, nil
return provider, defaultModel, nil
}
func (m *Manager) GetProvider(name string) (Provider, error) {
@@ -208,9 +221,9 @@ type StreamEvent struct {
}
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
Model string `json:"model"`
}