93 lines
2.0 KiB
Go
93 lines
2.0 KiB
Go
|
|
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
|
||
|
|
}
|