feat: add minimax provider support
This commit is contained in:
parent
5872e0f55e
commit
add918be91
4 changed files with 75 additions and 5 deletions
|
|
@ -161,6 +161,7 @@ type ProvidersConfig struct {
|
||||||
Nvidia ProviderConfig `json:"nvidia"`
|
Nvidia ProviderConfig `json:"nvidia"`
|
||||||
Moonshot ProviderConfig `json:"moonshot"`
|
Moonshot ProviderConfig `json:"moonshot"`
|
||||||
ShengSuanYun ProviderConfig `json:"shengsuanyun"`
|
ShengSuanYun ProviderConfig `json:"shengsuanyun"`
|
||||||
|
MiniMax ProviderConfig `json:"minimax"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProviderConfig struct {
|
type ProviderConfig struct {
|
||||||
|
|
@ -374,6 +375,9 @@ func (c *Config) GetAPIKey() string {
|
||||||
if c.Providers.ShengSuanYun.APIKey != "" {
|
if c.Providers.ShengSuanYun.APIKey != "" {
|
||||||
return c.Providers.ShengSuanYun.APIKey
|
return c.Providers.ShengSuanYun.APIKey
|
||||||
}
|
}
|
||||||
|
if c.Providers.MiniMax.APIKey != "" {
|
||||||
|
return c.Providers.MiniMax.APIKey
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ type HTTPProvider struct {
|
||||||
apiKey string
|
apiKey string
|
||||||
apiBase string
|
apiBase string
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
RequestSuffix string // Optional: override default "/chat/completions"
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPProvider(apiKey, apiBase, proxy string) *HTTPProvider {
|
func NewHTTPProvider(apiKey, apiBase, proxy string) *HTTPProvider {
|
||||||
|
|
@ -94,7 +95,12 @@ func (p *HTTPProvider) Chat(ctx context.Context, messages []Message, tools []Too
|
||||||
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
return nil, fmt.Errorf("failed to marshal request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", p.apiBase+"/chat/completions", bytes.NewReader(jsonData))
|
suffix := "/chat/completions"
|
||||||
|
if p.RequestSuffix != "" {
|
||||||
|
suffix = p.RequestSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "POST", p.apiBase+suffix, bytes.NewReader(jsonData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +124,6 @@ func (p *HTTPProvider) Chat(ctx context.Context, messages []Message, tools []Too
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return nil, fmt.Errorf("API request failed:\n Status: %d\n Body: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("API request failed:\n Status: %d\n Body: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.parseResponse(body)
|
return p.parseResponse(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,12 +144,20 @@ func (p *HTTPProvider) parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
FinishReason string `json:"finish_reason"`
|
FinishReason string `json:"finish_reason"`
|
||||||
} `json:"choices"`
|
} `json:"choices"`
|
||||||
Usage *UsageInfo `json:"usage"`
|
Usage *UsageInfo `json:"usage"`
|
||||||
|
BaseResp *struct {
|
||||||
|
StatusCode int `json:"status_code"`
|
||||||
|
StatusMsg string `json:"status_msg"`
|
||||||
|
} `json:"base_resp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if apiResponse.BaseResp != nil && apiResponse.BaseResp.StatusCode != 0 {
|
||||||
|
return nil, fmt.Errorf("provider error: [%d] %s", apiResponse.BaseResp.StatusCode, apiResponse.BaseResp.StatusMsg)
|
||||||
|
}
|
||||||
|
|
||||||
if len(apiResponse.Choices) == 0 {
|
if len(apiResponse.Choices) == 0 {
|
||||||
return &LLMResponse{
|
return &LLMResponse{
|
||||||
Content: "",
|
Content: "",
|
||||||
|
|
@ -297,6 +310,16 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
|
||||||
apiBase = "https://router.shengsuanyun.com/api/v1"
|
apiBase = "https://router.shengsuanyun.com/api/v1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "minimax":
|
||||||
|
if cfg.Providers.MiniMax.APIKey != "" {
|
||||||
|
apiKey = cfg.Providers.MiniMax.APIKey
|
||||||
|
apiBase = cfg.Providers.MiniMax.APIBase
|
||||||
|
if apiBase == "" {
|
||||||
|
apiBase = "https://api.minimax.io/v1"
|
||||||
|
}
|
||||||
|
// MiniMax requires special provider creation
|
||||||
|
return MiniMaxProvider(apiKey, apiBase), nil
|
||||||
|
}
|
||||||
case "claude-cli", "claudecode", "claude-code":
|
case "claude-cli", "claudecode", "claude-code":
|
||||||
workspace := cfg.Agents.Defaults.Workspace
|
workspace := cfg.Agents.Defaults.Workspace
|
||||||
if workspace == "" {
|
if workspace == "" {
|
||||||
|
|
@ -380,6 +403,14 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
|
||||||
apiBase = "https://integrate.api.nvidia.com/v1"
|
apiBase = "https://integrate.api.nvidia.com/v1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case (strings.Contains(lowerModel, "minimax") || strings.HasPrefix(model, "minimax/")) && cfg.Providers.MiniMax.APIKey != "":
|
||||||
|
apiKey = cfg.Providers.MiniMax.APIKey
|
||||||
|
apiBase = cfg.Providers.MiniMax.APIBase
|
||||||
|
if apiBase == "" {
|
||||||
|
apiBase = "https://api.minimax.io/v1"
|
||||||
|
}
|
||||||
|
return MiniMaxProvider(apiKey, apiBase), nil
|
||||||
|
|
||||||
case cfg.Providers.VLLM.APIBase != "":
|
case cfg.Providers.VLLM.APIBase != "":
|
||||||
apiKey = cfg.Providers.VLLM.APIKey
|
apiKey = cfg.Providers.VLLM.APIKey
|
||||||
apiBase = cfg.Providers.VLLM.APIBase
|
apiBase = cfg.Providers.VLLM.APIBase
|
||||||
|
|
|
||||||
7
pkg/providers/minimax_provider.go
Normal file
7
pkg/providers/minimax_provider.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package providers
|
||||||
|
|
||||||
|
func MiniMaxProvider(apiKey, apiBase string) *HTTPProvider {
|
||||||
|
p := NewHTTPProvider(apiKey, apiBase, "")
|
||||||
|
p.RequestSuffix = "/text/chatcompletion_v2"
|
||||||
|
return p
|
||||||
|
}
|
||||||
28
pkg/providers/minimax_provider_test.go
Normal file
28
pkg/providers/minimax_provider_test.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMiniMaxProvider_Chat(t *testing.T) {
|
||||||
|
apiKey := os.Getenv("MINIMAX_API_KEY")
|
||||||
|
if apiKey == "" {
|
||||||
|
t.Skip("Skipping MiniMax integration test: MINIMAX_API_KEY not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
apiBase := "https://api.minimax.io/v1"
|
||||||
|
provider := MiniMaxProvider(apiKey, apiBase)
|
||||||
|
|
||||||
|
resp, err := provider.Chat(context.Background(), []Message{{Role: "user", Content: "Hi"}}, nil, "M2-her", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Chat failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Content == "" {
|
||||||
|
t.Errorf("Expected non-empty content")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Response: %s", resp.Content)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue