Files
Luminary/internal/provider/openai/client.go
T
renjue 76ba500417
CI / docker (push) Successful in 2m4s
Initial commit: Luminary AI Gateway
OpenAI-compatible AI gateway with Vue admin UI, multi-provider egress,
ingress key governance, monitoring, and security controls.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 21:46:16 +08:00

95 lines
3.0 KiB
Go

package openai
import (
"context"
"encoding/json"
"fmt"
"github.com/rose_cat707/luminary/internal/model"
"github.com/rose_cat707/luminary/internal/provider"
)
type Client struct {
http *provider.HTTPClientWrapper
}
func New() *Client {
return &Client{http: provider.NewHTTPClientWrapper()}
}
func (c *Client) Type() string { return "openai" }
func (c *Client) cfg(baseURL string) provider.ProviderConfig {
return provider.ProviderConfig{
Type: model.ProviderOpenAI,
Category: model.CategoryLLM,
BaseURL: provider.NormalizeBaseURL(baseURL, model.ProviderOpenAI),
}
}
func (c *Client) ListModels(ctx context.Context, apiKey, baseURL string) ([]provider.ModelInfo, error) {
return c.ListModelsWithConfig(ctx, apiKey, provider.ProviderConfig{
Type: model.ProviderOpenAI,
BaseURL: provider.NormalizeBaseURL(baseURL, model.ProviderOpenAI),
})
}
func (c *Client) ListModelsWithConfig(ctx context.Context, apiKey string, cfg provider.ProviderConfig) ([]provider.ModelInfo, error) {
cfg.Type = model.ProviderOpenAI
cfg.BaseURL = provider.NormalizeBaseURL(cfg.BaseURL, model.ProviderOpenAI)
url := cfg.ResolveEndpointURL(provider.EndpointListModels)
resp, err := provider.ForwardHTTP(ctx, c.http.Client, "GET", url, apiKey, cfg.Type, nil, nil)
if err != nil {
return nil, err
}
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("list models: %s", string(resp.Body))
}
var out struct {
Data []struct {
ID string `json:"id"`
} `json:"data"`
}
if err := json.Unmarshal(resp.Body, &out); err != nil {
return nil, err
}
models := make([]provider.ModelInfo, 0, len(out.Data))
for _, m := range out.Data {
models = append(models, provider.ModelInfo{ID: m.ID, DisplayName: m.ID})
}
return models, nil
}
func (c *Client) ChatCompletion(ctx context.Context, apiKey, baseURL string, req *provider.ChatRequest) (*provider.ChatResponse, error) {
return c.ForwardWithConfig(ctx, apiKey, provider.ProviderConfig{
Type: model.ProviderOpenAI,
BaseURL: provider.NormalizeBaseURL(baseURL, model.ProviderOpenAI),
}, provider.EndpointChatCompletion, req.Raw)
}
func (c *Client) ForwardWithConfig(ctx context.Context, apiKey string, cfg provider.ProviderConfig, endpoint provider.EndpointType, body []byte) (*provider.ChatResponse, error) {
cfg.Type = model.ProviderOpenAI
cfg.BaseURL = provider.NormalizeBaseURL(cfg.BaseURL, model.ProviderOpenAI)
url := cfg.ResolveEndpointURL(endpoint)
resp, err := provider.ForwardHTTP(ctx, c.http.Client, "POST", url, apiKey, cfg.Type, body, nil)
if err != nil {
return nil, err
}
return &provider.ChatResponse{
StatusCode: resp.StatusCode,
Body: resp.Body,
TokensIn: resp.TokensIn,
TokensOut: resp.TokensOut,
}, nil
}
func (c *Client) HealthCheck(ctx context.Context, apiKey, baseURL string) error {
_, err := c.ListModels(ctx, apiKey, baseURL)
return err
}
func (c *Client) HealthCheckWithConfig(ctx context.Context, apiKey string, cfg provider.ProviderConfig) error {
_, err := c.ListModelsWithConfig(ctx, apiKey, cfg)
return err
}