117 lines
4.4 KiB
Go
117 lines
4.4 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"git.gobha.me/xcaliber/chat-switchboard/models"
|
|
)
|
|
|
|
// ── Provider Interface ──────────────────────
|
|
|
|
// Provider is the contract for LLM API adapters.
|
|
type Provider interface {
|
|
// ID returns the provider identifier (e.g. "openai", "anthropic").
|
|
ID() string
|
|
|
|
// ChatCompletion sends a non-streaming request and returns the full response.
|
|
ChatCompletion(ctx context.Context, cfg ProviderConfig, req CompletionRequest) (*CompletionResponse, error)
|
|
|
|
// StreamCompletion sends a streaming request and returns a channel of events.
|
|
// The channel is closed when the stream ends. Errors are sent as StreamEvents.
|
|
StreamCompletion(ctx context.Context, cfg ProviderConfig, req CompletionRequest) (<-chan StreamEvent, error)
|
|
|
|
// ListModels returns available models from this provider.
|
|
ListModels(ctx context.Context, cfg ProviderConfig) ([]Model, error)
|
|
}
|
|
|
|
// ── Configuration ───────────────────────────
|
|
|
|
// ProviderConfig holds credentials and endpoint for a configured provider.
|
|
// Populated from the provider_configs table at call time.
|
|
type ProviderConfig struct {
|
|
Endpoint string
|
|
APIKey string
|
|
CustomHeaders map[string]string // Extra HTTP headers (e.g. OpenRouter HTTP-Referer)
|
|
Settings map[string]interface{} // Provider-specific settings from config JSONB
|
|
}
|
|
|
|
// ── Request / Response Types ────────────────
|
|
|
|
// Message represents a chat message in the conversation.
|
|
type Message struct {
|
|
Role string `json:"role"` // user, assistant, system, tool
|
|
Content string `json:"content"`
|
|
|
|
// Tool calling fields (assistant → tool_calls, tool → tool_call_id)
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"` // set when assistant requests tools
|
|
ToolCallID string `json:"tool_call_id,omitempty"` // set for role="tool" result messages
|
|
Name string `json:"name,omitempty"` // tool name for role="tool"
|
|
}
|
|
|
|
// ToolCall represents a function call requested by the LLM.
|
|
type ToolCall struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"` // "function"
|
|
Function FunctionCall `json:"function"`
|
|
}
|
|
|
|
// FunctionCall is the function name and JSON arguments.
|
|
type FunctionCall struct {
|
|
Name string `json:"name"`
|
|
Arguments string `json:"arguments"`
|
|
}
|
|
|
|
// ToolDef describes a tool available to the LLM.
|
|
type ToolDef struct {
|
|
Type string `json:"type"` // "function"
|
|
Function FunctionDef `json:"function"`
|
|
}
|
|
|
|
// FunctionDef is the schema for a tool function.
|
|
type FunctionDef struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters json.RawMessage `json:"parameters"`
|
|
}
|
|
|
|
// CompletionRequest is the normalized request sent to any provider.
|
|
type CompletionRequest struct {
|
|
Model string `json:"model"`
|
|
Messages []Message `json:"messages"`
|
|
MaxTokens int `json:"max_tokens,omitempty"`
|
|
Temperature *float64 `json:"temperature,omitempty"`
|
|
TopP *float64 `json:"top_p,omitempty"`
|
|
Stream bool `json:"stream,omitempty"`
|
|
Tools []ToolDef `json:"tools,omitempty"` // available tools for function calling
|
|
}
|
|
|
|
// CompletionResponse is the normalized non-streaming response.
|
|
type CompletionResponse struct {
|
|
Content string `json:"content"`
|
|
Model string `json:"model"`
|
|
FinishReason string `json:"finish_reason"`
|
|
InputTokens int `json:"input_tokens"`
|
|
OutputTokens int `json:"output_tokens"`
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"` // set when finish_reason is "tool_calls"
|
|
}
|
|
|
|
// StreamEvent is a single chunk from a streaming response.
|
|
type StreamEvent struct {
|
|
Delta string `json:"delta,omitempty"`
|
|
Done bool `json:"done,omitempty"`
|
|
FinishReason string `json:"finish_reason,omitempty"`
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
|
Model string `json:"model,omitempty"`
|
|
Error error `json:"-"`
|
|
}
|
|
|
|
// Model represents an available model from a provider, with capabilities.
|
|
type Model struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name,omitempty"`
|
|
OwnedBy string `json:"owned_by,omitempty"`
|
|
Capabilities models.ModelCapabilities `json:"capabilities"`
|
|
Pricing *models.ModelPricing `json:"pricing,omitempty"`
|
|
}
|