核心概念
了解所有 go-llm-router 供應商共用的合約與正規化規則。
Agent 合約
所有供應商都實作相同介面:
type Agent interface {
Name() string
Send(
ctx context.Context,
messages []Message,
toolDefs []Tool,
reasoning Reasoning,
mode Mode,
) (*Output, int, error)
}
Send 接受 context、聊天訊息、可選的工具定義、正規化的推理強度與執行模式,回傳正規化的 Output、HTTP status code 與 error。呼叫端因此可以替換供應商,而不必改寫請求迴圈。
支援串流的供應商額外實作 StreamAgent,參數與 Send 完全一致:
type StreamAgent interface {
SendStream(
ctx context.Context,
messages []Message,
toolDefs []Tool,
reasoning Reasoning,
mode Mode,
) (<-chan StreamEvent, error)
}
core/claude 與 core/copilot 對外提供 SendStream。core/openaiCodex 與 core/grokOauth 在內部消化上游 SSE,仍以 Send 回傳完整的 core.Output。
| 事件型別 | 內容 |
|---|---|
StreamEventText |
TextDelta 輸出文字增量 |
StreamEventReasoning |
ReasoningDelta 推理摘要增量 |
StreamEventToolCall |
ToolCall 增量,含 index、ID、名稱或參數片段 |
StreamEventUsage |
正規化的 Usage |
StreamEventDone |
FinishReason |
StreamEventError |
Err |
訊息與多模態內容
Message 包含 Role、任意型別的 Content、可選的 ReasoningContent、模型產生的 ToolCalls,以及工具結果使用的 ToolCallID。Content 可以是字串或供應商支援的結構化內容。多模態請求使用 ContentPart,其中含 text 或帶 URL 與可選 Detail 的 ImageURL。
messages := []core.Message{
{Role: "user", Content: "Describe this image."},
{Role: "user", Content: []core.ContentPart{
{Type: "text", Text: "What is shown here?"},
{Type: "image_url", ImageURL: &core.ImageURL{URL: imageURL}},
}},
}
供應商路由
以 provider@model 名稱呼叫 router.New。選擇供應商時會忽略可選的方括號標籤,因此 claude[eu]@claude-sonnet-5 仍路由至 claude。compat@model 走 OpenAI 相容實作,並使用 BaseURL。
目前的 router key:claude、openai、gemini、grok、deepseek、nvidia、openrouter、cloudflare、compat、copilot、codex、grok-oauth。未知的 key 由 router.New 回傳錯誤。
推理強度
Reasoning 是具型別的列舉,取代早期的字串參數:
| 常數 | 字面值 | 別名 |
|---|---|---|
ReasoningNone |
none |
— |
ReasoningLow |
low |
minimal |
ReasoningMedium |
medium |
— |
ReasoningHigh |
high |
— |
ReasoningXHigh |
xhigh |
extra |
ReasoningMax |
max |
ultra |
ReasoningDefault 為 ReasoningMedium。ParseReasoning 解析字面值與別名,第二個回傳值標示是否命中;未命中時回傳預設值。
每個模型支援的區間不同。供應商適配器實作 ReasoningAgent,對外公開自身上下限:
type ReasoningAgent interface {
ReasoningLimits() (min, max Reasoning)
}
送出前由 ClampReasoning(r, lo, hi, provider, model) 夾到區間內,被夾住時以 slog 記錄 debug 訊息。呼叫端只需傳共用強度,不必自行組供應商欄位——Claude 走 thinking budget 或 output_config.effort、OpenAI 走 reasoning_effort 或 Responses reasoning.effort、Gemini 走 thinkingLevel 或 thinkingBudget,皆由適配器轉換。
執行模式與加速層
Mode 描述要求的服務層級:ModeDefault 與 ModeFast,ParseMode 解析 default 與 fast。
ModeFast 是能力請求。適配器先以 core.SupportFast(provider, model) 比對白名單,命中才加上供應商原生欄位;未命中則靜默維持標準層,不回傳錯誤——未列名的模型有些會直接拒絕該參數(例如 Claude Opus 4.7 回 400),事前擋掉比事後處理錯誤便宜。
| 路由 | 原生控制 | 白名單 |
|---|---|---|
| Claude | speed: "fast" + beta header fast-mode-2026-02-01 |
Opus 5、Opus 4.8 |
| OpenAI | service_tier: "fast" |
gpt-5.4 以上;codex 變體 5.3 以上;排除 -pro 與 -nano |
| Grok、Grok OAuth | service_tier: "priority" |
文字推理模型 |
| OpenRouter | service_tier: "priority" |
openai/、google/、x-ai/ 上游,再套用該上游的白名單 |
| 其他適配器 | 不送任何層級欄位 | — |
Gemini 的模型清單保留在 SupportFast 內,用於判斷 OpenRouter 的 google/ 路由;Gemini 適配器本身目前不送層級欄位。
供應商不保證請求值等於實際服務層級,因此歸因一律讀回應:OpenAI、Grok、OpenRouter 讀頂層 service_tier(正規化後放入 Output.ServiceTier),Claude 讀 usage.speed。回報值非 fast/priority 時,core.WarnFastDowngrade 以 slog 記錄降級警告;欄位為空代表供應商未回報,不視為降級。
工具呼叫
Tool 由 Type 與 ToolFunction(名稱、描述、JSON Schema 參數)組成。模型回傳的呼叫落在 Output.Choices[*].Message.ToolCalls。典型迴圈是把 assistant 訊息送回,逐一執行函式,再以 ToolCallID 送出 tool 訊息。
tools := []core.Tool{{
Type: "function",
Function: core.ToolFunction{
Name: "get_weather",
Description: "Look up weather for a city",
Parameters: json.RawMessage(`{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}`),
},
}}
out, _, err := agent.Send(ctx, messages, tools, core.ReasoningMedium, core.ModeDefault)
if err != nil {
return err
}
for _, call := range out.Choices[0].Message.ToolCalls {
fmt.Println(call.Function.Name, call.Function.Arguments)
}
Gemini 的 thinking 模型會在 ToolCall.ThoughtSignature 帶回簽章,續傳時需原樣送回。
用量正規化
各家 token 計數欄位命名不同。Usage.UnmarshalJSON 吸收 input_tokens / output_tokens、OpenAI 風格的 prompt_tokens / completion_tokens、cache 建立與 cache 讀取欄位,合併為單一結構:
| 欄位 | 意義 |
|---|---|
Input |
非快取的 input token |
Output |
產生的 output token |
CacheCreate |
寫入 prompt cache 的 token |
CacheRead |
由 cache 讀取的 input token |
計費與 UI 程式碼因此可直接消費 output.Usage,不必依供應商分支。
模型探索
各供應商套件提供 Models(ctx, config, filter) 回傳模型 ID 清單;core/copilot 與 core/gemini 另提供 ModelInfos,回傳含 Thinking、Efforts、Endpoints 的 core.ModelInfo。
core.ModelFilter{TextOnly: true} 會透過 core.IsTextModel 濾除影像、語音、影片、embedding 等非文字模型。
OAuth 與擴充
core/oauth/copilot、core/oauth/codex、core/oauth/grok 提供登入、載入、刷新與清除。Token 物件透過 router.Config.Token 傳入;CodexToken 與 GrokToken 提供 Expired(),並保留 60 秒安全緩衝。
core/openaiCodex 的 Agent 額外提供 GenerateImage,回傳 base64 影像資料與修訂後的 prompt。