Files
ModelRouter/internal/config/presets.go
JianFeeeee 624fd74b45 fix: anthropic tool-call round-trip, cache zero-hit parity, round-robin load balancing
anthropic.lua v3.0.0:
- Issue 1: tool_result/tool_use round-trip
- Issue 3: thinking default OFF (opt-in via extra_body.thinking)
- Issue 4: tool_choice mapping
- Issue 5: collect_blocks preserves unknown part types
- message_stop no longer emits done=true (was overwriting tool_calls finish_reason)
- cache_read_input_tokens normalized even at 0

gemini.lua:
- transform_response was missing cachedContentTokenCount

openai.lua (Issue 6):
- transform_error handles flat envelopes, nginx HTML, bare text

chat.go mergeUsage:
- Keep PromptTokensDetails even when CachedTokens=0

scheduler.go:
- Remove sort.SliceStable by Pref; round-robin cursor is the only LB mechanism

provider.go ModelAvailable:
- Also check Pref() > prefMin, persistently failing slots exit cands

presets.go:
- 17 built-in source templates

Tests: 6 new test functions, 2 updated for new semantics
2026-08-28 12:02:46 +08:00

213 lines
7.1 KiB
Go

package config
// Built-in preset source templates. Seeded into the runtime store on first
// startup so the WebUI can present "从模板创建" for popular providers — the
// user only needs to supply a name and API key.
//
// Model IDs verified against provider docs 2026-08-28. Providers ship new IDs
// frequently; treat these as a starting point and edit in the WebUI as needed.
var PresetTemplates = []SourceTemplate{
// ── 国内热门 ────────────────────────────────────────────────────────────
{
Name: "DeepSeek",
BaseURL: "https://api.deepseek.com",
Adapter: "deepseek",
MaxConcurrent: 8,
Models: []Model{
{ID: "deepseek-v4-flash", Priority: 100, Kind: "chat"},
{ID: "deepseek-v4-pro", Priority: 90, Kind: "chat"},
{ID: "deepseek-v4-flash-vision-exp", Priority: 60, Kind: "chat"},
},
},
{
Name: "智谱 GLM",
BaseURL: "https://open.bigmodel.cn/api/paas/v4",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "glm-5.3", Priority: 100, Kind: "chat"},
{ID: "glm-5.3-flash", Priority: 90, Kind: "chat"},
{ID: "glm-5.2", Priority: 80, Kind: "chat"},
{ID: "glm-5.1", Priority: 60, Kind: "chat"},
},
},
{
Name: "Kimi / Moonshot",
BaseURL: "https://api.moonshot.cn/v1",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "kimi-k3", Priority: 100, Kind: "chat"},
{ID: "kimi-k2.7-code", Priority: 90, Kind: "chat"},
{ID: "kimi-k2.7-code-highspeed", Priority: 85, Kind: "chat"},
{ID: "kimi-k2.6", Priority: 70, Kind: "chat"},
},
},
{
Name: "SiliconFlow",
BaseURL: "https://api.siliconflow.cn/v1",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "deepseek-ai/DeepSeek-V4-Pro", Priority: 100, Kind: "chat"},
{ID: "deepseek-ai/DeepSeek-V4-Flash", Priority: 90, Kind: "chat"},
{ID: "moonshotai/Kimi-K2.6", Priority: 80, Kind: "chat"},
{ID: "zai-org/GLM-5.1", Priority: 70, Kind: "chat"},
{ID: "Kwai-Kolors/Kolors", Priority: 50, Kind: "image"},
},
},
{
Name: "讯飞星火 (Spark)",
BaseURL: "https://spark-api-open.xf-yun.com/v1",
Adapter: "openai",
MaxConcurrent: 4,
Models: []Model{
{ID: "4.0Ultra", Priority: 100, Kind: "chat"},
{ID: "generalv3.5", Priority: 80, Kind: "chat"},
{ID: "max-32k", Priority: 70, Kind: "chat"},
},
},
{
Name: "阿里云 通义千问",
BaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "qwen3.8-max", Priority: 100, Kind: "chat"},
{ID: "qwen3.8-flash", Priority: 90, Kind: "chat"},
{ID: "qwen3.7-plus", Priority: 85, Kind: "chat"},
{ID: "deepseek-v4-pro", Priority: 70, Kind: "chat"},
{ID: "kimi-k3", Priority: 70, Kind: "chat"},
},
},
{
Name: "百度 千帆",
BaseURL: "https://qianfan.baidubce.com/v2",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "ernie-5.0-turbo", Priority: 100, Kind: "chat"},
{ID: "ernie-5.0", Priority: 90, Kind: "chat"},
{ID: "deepseek-v4-pro", Priority: 70, Kind: "chat"},
},
},
{
Name: "豆包 (火山方舟)",
BaseURL: "https://ark.cn-beijing.volces.com/api/v3",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "doubao-seed-2.0-pro", Priority: 100, Kind: "chat"},
{ID: "doubao-seed-2.0", Priority: 90, Kind: "chat"},
{ID: "doubao-seed-2.0-flash", Priority: 80, Kind: "chat"},
},
},
{
Name: "MiniMax",
BaseURL: "https://api.minimax.chat/v1",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "MiniMax-M3", Priority: 100, Kind: "chat"},
{ID: "MiniMax-M2.5", Priority: 80, Kind: "chat"},
},
},
// ── 国际主流 ────────────────────────────────────────────────────────────
{
Name: "OpenAI",
BaseURL: "https://api.openai.com/v1",
Adapter: "openai",
MaxConcurrent: 8,
Models: []Model{
{ID: "gpt-5.6-sol", Priority: 100, Kind: "chat"},
{ID: "gpt-5.6-terra", Priority: 90, Kind: "chat"},
{ID: "gpt-5.6-luna", Priority: 80, Kind: "chat"},
},
},
{
Name: "Anthropic Claude",
BaseURL: "https://api.anthropic.com",
Adapter: "anthropic",
MaxConcurrent: 8,
Models: []Model{
{ID: "claude-opus-5", Priority: 100, Kind: "chat"},
{ID: "claude-fable-5", Priority: 95, Kind: "chat"},
{ID: "claude-sonnet-5", Priority: 85, Kind: "chat"},
{ID: "claude-haiku-4-5", Priority: 70, Kind: "chat"},
},
},
{
Name: "Google Gemini",
BaseURL: "https://generativelanguage.googleapis.com/v1beta",
Adapter: "gemini",
MaxConcurrent: 8,
Models: []Model{
{ID: "gemini-3.6-flash", Priority: 100, Kind: "chat"},
{ID: "gemini-3.5-flash", Priority: 90, Kind: "chat"},
{ID: "gemini-3.5-flash-lite", Priority: 80, Kind: "chat"},
{ID: "gemini-3.1-pro", Priority: 85, Kind: "chat"},
},
},
{
Name: "Groq",
BaseURL: "https://api.groq.com/openai/v1",
Adapter: "groq",
MaxConcurrent: 8,
Models: []Model{
{ID: "openai/gpt-oss-120b", Priority: 100, Kind: "chat"},
{ID: "openai/gpt-oss-20b", Priority: 80, Kind: "chat"},
{ID: "groq/compound", Priority: 70, Kind: "chat"},
},
},
{
Name: "Mistral",
BaseURL: "https://api.mistral.ai/v1",
Adapter: "mistral",
MaxConcurrent: 8,
Models: []Model{
{ID: "mistral-medium-latest", Priority: 100, Kind: "chat"},
{ID: "mistral-large-latest", Priority: 90, Kind: "chat"},
{ID: "codestral-latest", Priority: 85, Kind: "chat"},
},
},
{
Name: "OpenRouter",
BaseURL: "https://openrouter.ai/api/v1",
Adapter: "openai",
MaxConcurrent: 8,
Headers: map[string]string{
"HTTP-Referer": "http://localhost:8080",
"X-Title": "ModelRouter",
},
Models: []Model{
{ID: "openrouter/auto", Priority: 100, Kind: "chat"},
{ID: "deepseek/deepseek-v4-flash", Priority: 90, Kind: "chat"},
{ID: "anthropic/claude-opus-5", Priority: 85, Kind: "chat"},
{ID: "openai/gpt-5.6-sol", Priority: 85, Kind: "chat"},
},
},
{
Name: "GitHub Models",
BaseURL: "https://models.inference.ai.azure.com",
Adapter: "github",
MaxConcurrent: 8,
Models: []Model{
{ID: "gpt-5.6-sol", Priority: 100, Kind: "chat"},
{ID: "gpt-5.6-luna", Priority: 80, Kind: "chat"},
},
},
// ── 本地模型 ────────────────────────────────────────────────────────────
{
Name: "Ollama (localhost)",
BaseURL: "http://127.0.0.1:11434",
Adapter: "ollama",
Endpoint: "/api/chat",
MaxConcurrent: 4,
Models: []Model{
{ID: "qwen3", Priority: 80, Kind: "chat"},
{ID: "deepseek-r1", Priority: 80, Kind: "chat"},
{ID: "llama3.3", Priority: 70, Kind: "chat"},
},
},
}