Files
GovAI/server/cmd/check-providers/main.go
T
selfrelease 96930b585c 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 个应用现在自动使用本地模型,无需手动配置。
2026-06-22 18:46:44 +08:00

134 lines
3.2 KiB
Go

package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/joho/godotenv"
)
func main() {
// 加载环境变量
_ = godotenv.Load("../../.env")
dbURL := os.Getenv("DATABASE_URL")
if dbURL == "" {
dbURL = "postgres://freedak:@localhost:5432/govai_portal?sslmode=disable"
}
pool, err := pgxpool.New(context.Background(), dbURL)
if err != nil {
log.Fatalf("无法连接数据库: %v", err)
}
defer pool.Close()
fmt.Println("=== 数据库中的模型提供商配置 ===")
rows, err := pool.Query(context.Background(), `
SELECT id, name, base_url,
SUBSTRING(api_key_encrypted, 1, 20) as api_key_prefix,
models, is_active, priority, config
FROM model_providers
ORDER BY priority DESC, created_at
`)
if err != nil {
log.Fatalf("查询失败: %v", err)
}
defer rows.Close()
count := 0
for rows.Next() {
var id, name, baseURL, apiKeyPrefix string
var modelsJSON, configJSON []byte
var isActive bool
var priority int
err := rows.Scan(&id, &name, &baseURL, &apiKeyPrefix, &modelsJSON, &isActive, &priority, &configJSON)
if err != nil {
log.Printf("扫描行失败: %v", err)
continue
}
count++
fmt.Printf("【提供商 %d】\n", count)
fmt.Printf("ID: %s\n", id)
fmt.Printf("名称: %s\n", name)
fmt.Printf("Base URL: %s\n", baseURL)
fmt.Printf("API Key: %s...\n", apiKeyPrefix)
fmt.Printf("激活状态: %v\n", isActive)
fmt.Printf("优先级: %d\n", priority)
// 解析 models
var models []map[string]interface{}
if err := json.Unmarshal(modelsJSON, &models); err == nil {
fmt.Printf("可用模型: ")
for i, m := range models {
if i > 0 {
fmt.Print(", ")
}
fmt.Printf("%v", m["id"])
}
fmt.Println()
}
// 解析 config
var config map[string]interface{}
if err := json.Unmarshal(configJSON, &config); err == nil {
fmt.Printf("Provider 类型: %v\n", config["provider"])
fmt.Printf("默认模型: %v\n", config["default_model"])
}
fmt.Println()
}
if count == 0 {
fmt.Println("❌ 数据库中没有任何模型提供商配置")
fmt.Println("提示: 运行种子数据脚本来初始化配置")
} else {
fmt.Printf("✅ 共找到 %d 个提供商配置\n", count)
}
// 查询应用配置中的模型使用情况
fmt.Println("\n=== 应用配置中的模型使用情况 ===")
appRows, err := pool.Query(context.Background(), `
SELECT name,
COALESCE(app_config->>'model', '未配置') as model,
status
FROM applications
WHERE status = 'approved'
ORDER BY created_at DESC
LIMIT 10
`)
if err != nil {
log.Printf("查询应用失败: %v", err)
return
}
defer appRows.Close()
appCount := 0
modelStats := make(map[string]int)
for appRows.Next() {
var name, model, status string
if err := appRows.Scan(&name, &model, &status); err != nil {
continue
}
appCount++
modelStats[model]++
fmt.Printf("应用: %-30s | 模型: %-15s | 状态: %s\n", name, model, status)
}
if appCount > 0 {
fmt.Printf("\n✅ 共查询到 %d 个已批准的应用\n\n", appCount)
fmt.Println("模型使用统计:")
for model, count := range modelStats {
fmt.Printf(" - %-15s: %d 个应用\n", model, count)
}
}
}