Files
odidere/internal/llm/client_models.go

93 lines
2.0 KiB
Go
Raw Normal View History

package llm
import (
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
)
// ListModels returns available models from the LLM server.
func (c *Client) ListModels(ctx context.Context) ([]Model, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
req, err := http.NewRequestWithContext(
ctx, http.MethodGet, c.baseURL+"/models", nil,
)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
if c.key != "" {
req.Header.Set("Authorization", "Bearer "+c.key)
}
req.Header.Set("Content-Type", "application/json")
res, err := c.httpc.Do(req)
if err != nil {
return nil, fmt.Errorf("list models: %w", err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
body, err := io.ReadAll(res.Body)
if err != nil {
c.log.ErrorContext(
ctx,
"list models: failed to read error response body",
slog.Any("error", err),
)
return nil, fmt.Errorf(
"list models: status code %d", res.StatusCode,
)
}
var apiError struct {
Error *struct {
Type string `json:"type"`
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.Unmarshal(
body, &apiError,
); err == nil && apiError.Error != nil {
c.log.ErrorContext(
ctx,
"list models: request error",
slog.Int("status", res.StatusCode),
slog.String("code", apiError.Error.Code),
slog.String(
"message", apiError.Error.Message,
),
slog.String("type", apiError.Error.Type),
)
return nil, fmt.Errorf(
"list models: %s: %s",
apiError.Error.Code,
apiError.Error.Message,
)
}
c.log.ErrorContext(
ctx,
"list models: API error",
slog.Int("status", res.StatusCode),
slog.String("body", string(body)),
)
return nil, fmt.Errorf(
"list models: %d: %s",
res.StatusCode, string(body),
)
}
var body ModelsResponse
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
return nil, fmt.Errorf(
"list models: decode response: %w", err,
)
}
return body.Data, nil
}