mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
6e7149509a
Add 2-layer fallback system (text + image) with automatic candidate resolution. Includes error classifier (~40 patterns), per-provider cooldown (exponential backoff), and model reference parsing. - FailoverError/FailoverReason types for structured error handling - ErrorClassifier with rate_limit, billing, auth, timeout patterns - FallbackChain with cooldown management and candidate rotation - ModelRef parser for provider/model string format - 128 tests, 95%+ coverage
99 lines
2.8 KiB
Go
99 lines
2.8 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
type ToolCall struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type,omitempty"`
|
|
Function *FunctionCall `json:"function,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Arguments map[string]interface{} `json:"arguments,omitempty"`
|
|
}
|
|
|
|
type FunctionCall struct {
|
|
Name string `json:"name"`
|
|
Arguments string `json:"arguments"`
|
|
}
|
|
|
|
type LLMResponse struct {
|
|
Content string `json:"content"`
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
|
FinishReason string `json:"finish_reason"`
|
|
Usage *UsageInfo `json:"usage,omitempty"`
|
|
}
|
|
|
|
type UsageInfo struct {
|
|
PromptTokens int `json:"prompt_tokens"`
|
|
CompletionTokens int `json:"completion_tokens"`
|
|
TotalTokens int `json:"total_tokens"`
|
|
}
|
|
|
|
type Message struct {
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
|
ToolCallID string `json:"tool_call_id,omitempty"`
|
|
}
|
|
|
|
type LLMProvider interface {
|
|
Chat(ctx context.Context, messages []Message, tools []ToolDefinition, model string, options map[string]interface{}) (*LLMResponse, error)
|
|
GetDefaultModel() string
|
|
}
|
|
|
|
// FailoverReason classifies why an LLM request failed for fallback decisions.
|
|
type FailoverReason string
|
|
|
|
const (
|
|
FailoverAuth FailoverReason = "auth"
|
|
FailoverRateLimit FailoverReason = "rate_limit"
|
|
FailoverBilling FailoverReason = "billing"
|
|
FailoverTimeout FailoverReason = "timeout"
|
|
FailoverFormat FailoverReason = "format"
|
|
FailoverOverloaded FailoverReason = "overloaded"
|
|
FailoverUnknown FailoverReason = "unknown"
|
|
)
|
|
|
|
// FailoverError wraps an LLM provider error with classification metadata.
|
|
type FailoverError struct {
|
|
Reason FailoverReason
|
|
Provider string
|
|
Model string
|
|
Status int
|
|
Wrapped error
|
|
}
|
|
|
|
func (e *FailoverError) Error() string {
|
|
return fmt.Sprintf("failover(%s): provider=%s model=%s status=%d: %v",
|
|
e.Reason, e.Provider, e.Model, e.Status, e.Wrapped)
|
|
}
|
|
|
|
func (e *FailoverError) Unwrap() error {
|
|
return e.Wrapped
|
|
}
|
|
|
|
// IsRetriable returns true if this error should trigger fallback to next candidate.
|
|
// Non-retriable: Format errors (bad request structure, image dimension/size).
|
|
func (e *FailoverError) IsRetriable() bool {
|
|
return e.Reason != FailoverFormat
|
|
}
|
|
|
|
// ModelConfig holds primary model and fallback list.
|
|
type ModelConfig struct {
|
|
Primary string
|
|
Fallbacks []string
|
|
}
|
|
|
|
type ToolDefinition struct {
|
|
Type string `json:"type"`
|
|
Function ToolFunctionDefinition `json:"function"`
|
|
}
|
|
|
|
type ToolFunctionDefinition struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters map[string]interface{} `json:"parameters"`
|
|
}
|