Add Azure OpenAI provider
This commit is contained in:
@@ -28,9 +28,10 @@ type ServerConfig struct {
|
||||
|
||||
// ProvidersConfig wraps supported provider settings.
|
||||
type ProvidersConfig struct {
|
||||
Google ProviderConfig `yaml:"google"`
|
||||
Anthropic ProviderConfig `yaml:"anthropic"`
|
||||
OpenAI ProviderConfig `yaml:"openai"`
|
||||
Google ProviderConfig `yaml:"google"`
|
||||
Anthropic ProviderConfig `yaml:"anthropic"`
|
||||
OpenAI ProviderConfig `yaml:"openai"`
|
||||
AzureOpenAI AzureOpenAIConfig `yaml:"azureopenai"`
|
||||
}
|
||||
|
||||
// ProviderConfig contains shared provider configuration fields.
|
||||
@@ -40,6 +41,14 @@ type ProviderConfig struct {
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
}
|
||||
|
||||
// AzureOpenAIConfig contains Azure-specific settings.
|
||||
type AzureOpenAIConfig struct {
|
||||
APIKey string `yaml:"api_key"`
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
DeploymentID string `yaml:"deployment_id"`
|
||||
APIVersion string `yaml:"api_version"`
|
||||
}
|
||||
|
||||
// Load reads and parses a YAML configuration file and applies env overrides.
|
||||
func Load(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
@@ -60,6 +69,20 @@ func (cfg *Config) applyEnvOverrides() {
|
||||
overrideAPIKey(&cfg.Providers.Google, "GOOGLE_API_KEY")
|
||||
overrideAPIKey(&cfg.Providers.Anthropic, "ANTHROPIC_API_KEY")
|
||||
overrideAPIKey(&cfg.Providers.OpenAI, "OPENAI_API_KEY")
|
||||
|
||||
// Azure OpenAI overrides
|
||||
if v := os.Getenv("AZURE_OPENAI_API_KEY"); v != "" {
|
||||
cfg.Providers.AzureOpenAI.APIKey = v
|
||||
}
|
||||
if v := os.Getenv("AZURE_OPENAI_ENDPOINT"); v != "" {
|
||||
cfg.Providers.AzureOpenAI.Endpoint = v
|
||||
}
|
||||
if v := os.Getenv("AZURE_OPENAI_DEPLOYMENT_ID"); v != "" {
|
||||
cfg.Providers.AzureOpenAI.DeploymentID = v
|
||||
}
|
||||
if v := os.Getenv("AZURE_OPENAI_API_VERSION"); v != "" {
|
||||
cfg.Providers.AzureOpenAI.APIVersion = v
|
||||
}
|
||||
}
|
||||
|
||||
func overrideAPIKey(cfg *ProviderConfig, envKey string) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/openai/openai-go"
|
||||
"github.com/openai/openai-go/azure"
|
||||
"github.com/openai/openai-go/option"
|
||||
|
||||
"github.com/yourusername/go-llm-gateway/internal/api"
|
||||
@@ -15,12 +16,14 @@ import (
|
||||
const Name = "openai"
|
||||
|
||||
// Provider implements the OpenAI SDK integration.
|
||||
// It supports both direct OpenAI API and Azure-hosted endpoints.
|
||||
type Provider struct {
|
||||
cfg config.ProviderConfig
|
||||
client *openai.Client
|
||||
azure bool
|
||||
}
|
||||
|
||||
// New constructs a Provider from configuration.
|
||||
// New constructs a Provider for the direct OpenAI API.
|
||||
func New(cfg config.ProviderConfig) *Provider {
|
||||
var client *openai.Client
|
||||
if cfg.APIKey != "" {
|
||||
@@ -33,6 +36,32 @@ func New(cfg config.ProviderConfig) *Provider {
|
||||
}
|
||||
}
|
||||
|
||||
// NewAzure constructs a Provider targeting Azure OpenAI.
|
||||
// Azure OpenAI uses the OpenAI SDK with the azure subpackage for proper
|
||||
// endpoint routing, api-version query parameter, and API key header.
|
||||
func NewAzure(azureCfg config.AzureOpenAIConfig) *Provider {
|
||||
var client *openai.Client
|
||||
if azureCfg.APIKey != "" && azureCfg.Endpoint != "" {
|
||||
apiVersion := azureCfg.APIVersion
|
||||
if apiVersion == "" {
|
||||
apiVersion = "2024-12-01-preview"
|
||||
}
|
||||
c := openai.NewClient(
|
||||
azure.WithEndpoint(azureCfg.Endpoint, apiVersion),
|
||||
azure.WithAPIKey(azureCfg.APIKey),
|
||||
)
|
||||
client = &c
|
||||
}
|
||||
return &Provider{
|
||||
cfg: config.ProviderConfig{
|
||||
APIKey: azureCfg.APIKey,
|
||||
Model: azureCfg.DeploymentID,
|
||||
},
|
||||
client: client,
|
||||
azure: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the provider identifier.
|
||||
func (p *Provider) Name() string { return Name }
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ func NewRegistry(cfg config.ProvidersConfig) (*Registry, error) {
|
||||
if cfg.Anthropic.APIKey != "" {
|
||||
reg.providers[anthropicprovider.Name] = anthropicprovider.New(cfg.Anthropic)
|
||||
}
|
||||
if cfg.OpenAI.APIKey != "" {
|
||||
if cfg.AzureOpenAI.APIKey != "" && cfg.AzureOpenAI.Endpoint != "" {
|
||||
reg.providers[openaiprovider.Name] = openaiprovider.NewAzure(cfg.AzureOpenAI)
|
||||
} else if cfg.OpenAI.APIKey != "" {
|
||||
reg.providers[openaiprovider.Name] = openaiprovider.New(cfg.OpenAI)
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ func (r *Registry) Get(name string) (Provider, bool) {
|
||||
func (r *Registry) Default(model string) (Provider, error) {
|
||||
if model != "" {
|
||||
switch {
|
||||
case strings.HasPrefix(model, "gpt") || strings.HasPrefix(model, "o1"):
|
||||
case strings.HasPrefix(model, "gpt") || strings.HasPrefix(model, "o1") || strings.HasPrefix(model, "o3"):
|
||||
if p, ok := r.providers[openaiprovider.Name]; ok {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user