Add support for multiple providers
This commit is contained in:
@@ -20,8 +20,6 @@ import (
|
||||
type Config struct {
|
||||
// Key is the API key for authentication.
|
||||
Key string `yaml:"key"`
|
||||
// Model is the model identifier.
|
||||
Model string `yaml:"model"`
|
||||
// SystemMessage is prepended to all conversations.
|
||||
SystemMessage string `yaml:"system_message"`
|
||||
// Timeout is the maximum duration for a query (e.g., "5m").
|
||||
@@ -33,9 +31,6 @@ type Config struct {
|
||||
|
||||
// Validate checks that required configuration values are present and valid.
|
||||
func (cfg Config) Validate() error {
|
||||
if cfg.Model == "" {
|
||||
return fmt.Errorf("missing model")
|
||||
}
|
||||
if cfg.Timeout != "" {
|
||||
if _, err := time.ParseDuration(cfg.Timeout); err != nil {
|
||||
return fmt.Errorf("invalid timeout: %w", err)
|
||||
@@ -51,7 +46,6 @@ func (cfg Config) Validate() error {
|
||||
type Client struct {
|
||||
client *openai.Client
|
||||
log *slog.Logger
|
||||
model string
|
||||
registry *tool.Registry
|
||||
systemMessage string
|
||||
timeout time.Duration
|
||||
@@ -71,7 +65,6 @@ func NewClient(
|
||||
|
||||
llm := &Client{
|
||||
log: log,
|
||||
model: cfg.Model,
|
||||
systemMessage: cfg.SystemMessage,
|
||||
registry: registry,
|
||||
}
|
||||
@@ -115,17 +108,11 @@ func (c *Client) ListModels(ctx context.Context) ([]openai.Model, error) {
|
||||
return res.Models, nil
|
||||
}
|
||||
|
||||
// DefaultModel returns the configured default model.
|
||||
func (c *Client) DefaultModel() string {
|
||||
return c.model
|
||||
}
|
||||
|
||||
// ErrMaxIterations is returned when the agent loop exceeds the configured
|
||||
// maximum number of iterations.
|
||||
var ErrMaxIterations = fmt.Errorf("max iterations exceeded")
|
||||
|
||||
// Query sends messages to the LLM using the specified model.
|
||||
// If model is empty, uses the default configured model.
|
||||
// If systemMessage is non-empty, it overrides the configured system message.
|
||||
// maxIterations caps the number of agent loop iterations; a value of 0
|
||||
// means unlimited (no cap).
|
||||
@@ -141,11 +128,6 @@ func (c *Client) Query(
|
||||
ctx, cancel := context.WithTimeout(ctx, c.timeout)
|
||||
defer cancel()
|
||||
|
||||
// Fallback to the default model.
|
||||
if model == "" {
|
||||
model = c.model
|
||||
}
|
||||
|
||||
// Use per-request system message if provided, otherwise fall back to config.
|
||||
effectiveMessage := c.systemMessage
|
||||
if systemMessage != "" {
|
||||
@@ -273,11 +255,6 @@ func (c *Client) QueryStream(
|
||||
ctx, cancel := context.WithTimeout(ctx, c.timeout)
|
||||
defer cancel()
|
||||
|
||||
// Fallback to the default model.
|
||||
if model == "" {
|
||||
model = c.model
|
||||
}
|
||||
|
||||
// Use per-request system message if provided, otherwise fall back to config.
|
||||
effectiveMessage := c.systemMessage
|
||||
if systemMessage != "" {
|
||||
@@ -412,11 +389,6 @@ func (c *Client) QueryStream(
|
||||
result = fmt.Sprintf(
|
||||
`{"ok": false, "error": %q}`, err,
|
||||
)
|
||||
} else {
|
||||
c.log.Info(
|
||||
"called tool",
|
||||
slog.String("name", tc.Function.Name),
|
||||
)
|
||||
}
|
||||
// Content cannot be empty.
|
||||
if strings.TrimSpace(result) == "" {
|
||||
|
||||
@@ -16,23 +16,13 @@ func TestConfigValidate(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing model",
|
||||
cfg: Config{
|
||||
URL: "http://localhost:8080",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing URL",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
},
|
||||
name: "missing URL",
|
||||
cfg: Config{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid timeout",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
Timeout: "not-a-duration",
|
||||
},
|
||||
@@ -41,15 +31,13 @@ func TestConfigValidate(t *testing.T) {
|
||||
{
|
||||
name: "valid minimal config",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
URL: "http://localhost:8080",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid config with timeout",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
Timeout: "15m",
|
||||
},
|
||||
@@ -58,7 +46,6 @@ func TestConfigValidate(t *testing.T) {
|
||||
{
|
||||
name: "valid config with complex timeout",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
Timeout: "1h30m45s",
|
||||
},
|
||||
@@ -68,7 +55,6 @@ func TestConfigValidate(t *testing.T) {
|
||||
name: "valid full config",
|
||||
cfg: Config{
|
||||
Key: "sk-test-key",
|
||||
Model: "test-model",
|
||||
SystemMessage: "You are a helpful assistant.",
|
||||
Timeout: "30m",
|
||||
URL: "http://localhost:8080",
|
||||
@@ -104,15 +90,13 @@ func TestNewClient(t *testing.T) {
|
||||
{
|
||||
name: "valid config without timeout",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
URL: "http://localhost:8080",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid config with timeout",
|
||||
cfg: Config{
|
||||
Model: "test-model",
|
||||
URL: "http://localhost:8080",
|
||||
Timeout: "10m",
|
||||
},
|
||||
@@ -122,7 +106,6 @@ func TestNewClient(t *testing.T) {
|
||||
name: "valid config with all fields",
|
||||
cfg: Config{
|
||||
Key: "test-key",
|
||||
Model: "test-model",
|
||||
SystemMessage: "Test message",
|
||||
Timeout: "5m",
|
||||
URL: "http://localhost:8080",
|
||||
@@ -147,22 +130,3 @@ func TestNewClient(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientDefaultModel(t *testing.T) {
|
||||
cfg := Config{
|
||||
Model: "my-custom-model",
|
||||
URL: "http://localhost:8080",
|
||||
}
|
||||
|
||||
client, err := NewClient(cfg, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClient() error = %v", err)
|
||||
}
|
||||
|
||||
if got := client.DefaultModel(); got != "my-custom-model" {
|
||||
t.Errorf(
|
||||
"DefaultModel() = %q, want %q",
|
||||
got, "my-custom-model",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user