feat: support choosing chatCompletionV2 or chatCompletionPro API for minimax provider (#1593)

This commit is contained in:
韩贤涛
2024-12-15 15:12:00 +08:00
committed by GitHub
parent 0ba63e5dd4
commit 8544fa604d
3 changed files with 68 additions and 89 deletions

View File

@@ -174,9 +174,10 @@ Mistral 所对应的 `type` 为 `mistral`。它并无特有的配置字段。
MiniMax所对应的 `type``minimax`。它特有的配置字段如下: MiniMax所对应的 `type``minimax`。它特有的配置字段如下:
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 | | 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| ---------------- | -------- | ------------------------------------------------------------ | ------ | ------------------------------------------------------------ | | ---------------- | -------- | ------------------------------ | ------ |----------------------------------------------------------------|
| `minimaxGroupId` | string | 当使用`abab6.5-chat`, `abab6.5s-chat`, `abab5.5s-chat`, `abab5.5-chat`四种模型时必填 | - | 当使用`abab6.5-chat`, `abab6.5s-chat`, `abab5.5s-chat`, `abab5.5-chat`四种模型时会使用ChatCompletion Pro需要设置groupID | | `minimaxApiType` | string | v2 和 pro 中选填一项 | v2 | v2 代表 ChatCompletion v2 APIpro 代表 ChatCompletion Pro API |
| `minimaxGroupId` | string | `minimaxApiType` 为 pro 时必填 | - | `minimaxApiType` 为 pro 时使用 ChatCompletion Pro API需要设置 groupID |
#### Anthropic Claude #### Anthropic Claude
@@ -1000,17 +1001,16 @@ provider:
apiTokens: apiTokens:
- "YOUR_MINIMAX_API_TOKEN" - "YOUR_MINIMAX_API_TOKEN"
modelMapping: modelMapping:
"gpt-3": "abab6.5g-chat" "gpt-3": "abab6.5s-chat"
"gpt-4": "abab6.5-chat" "gpt-4": "abab6.5g-chat"
"*": "abab6.5g-chat" "*": "abab6.5t-chat"
minimaxGroupId: "YOUR_MINIMAX_GROUP_ID"
``` ```
**请求示例** **请求示例**
```json ```json
{ {
"model": "gpt-4-turbo", "model": "gpt-3",
"messages": [ "messages": [
{ {
"role": "user", "role": "user",
@@ -1025,27 +1025,33 @@ provider:
```json ```json
{ {
"id": "02b2251f8c6c09d68c1743f07c72afd7", "id": "03ac4fcfe1c6cc9c6a60f9d12046e2b4",
"choices": [ "choices": [
{ {
"finish_reason": "stop", "finish_reason": "stop",
"index": 0, "index": 0,
"message": { "message": {
"content": "你好我是MM智能助理一款由MiniMax自研的大型语言模型。我可以帮助你解答问题提供信息进行对话等。有什么可以帮助你的吗?", "content": "你好我是一个由MiniMax公司研发的大型语言模型名为MM智能助理。我可以帮助答问题提供信息进行对话和执行多种语言处理任务。如果你有任何问题或需要帮助,请随时告诉我!",
"role": "assistant" "role": "assistant",
"name": "MM智能助理",
"audio_content": ""
} }
} }
], ],
"created": 1717760544, "created": 1734155471,
"model": "abab6.5s-chat", "model": "abab6.5s-chat",
"object": "chat.completion", "object": "chat.completion",
"usage": { "usage": {
"total_tokens": 106 "total_tokens": 116,
"total_characters": 0,
"prompt_tokens": 70,
"completion_tokens": 46
}, },
"input_sensitive": false, "input_sensitive": false,
"output_sensitive": false, "output_sensitive": false,
"input_sensitive_type": 0, "input_sensitive_type": 0,
"output_sensitive_type": 0, "output_sensitive_type": 0,
"output_sensitive_int": 0,
"base_resp": { "base_resp": {
"status_code": 0, "status_code": 0,
"status_msg": "" "status_msg": ""

View File

@@ -11,47 +11,37 @@ import (
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper" "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm" "github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types" "github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
) )
// minimaxProvider is the provider for minimax service. // minimaxProvider is the provider for minimax service.
const ( const (
minimaxDomain = "api.minimax.chat" minimaxApiTypeV2 = "v2" // minimaxApiTypeV2 represents chat completion V2 API.
// minimaxChatCompletionV2Path 接口请求响应格式与OpenAI相同 minimaxApiTypePro = "pro" // minimaxApiTypePro represents chat completion Pro API.
// 接口文档: https://platform.minimaxi.com/document/guides/chat-model/V2?id=65e0736ab2845de20908e2dd minimaxDomain = "api.minimax.chat"
// minimaxChatCompletionV2Path represents the API path for chat completion V2 API which has a response format similar to OpenAI's.
minimaxChatCompletionV2Path = "/v1/text/chatcompletion_v2" minimaxChatCompletionV2Path = "/v1/text/chatcompletion_v2"
// minimaxChatCompletionProPath 接口请求响应格式与OpenAI不同 // minimaxChatCompletionProPath represents the API path for chat completion Pro API which has a different response format from OpenAI's.
// 接口文档: https://platform.minimaxi.com/document/guides/chat-model/pro/api?id=6569c85948bc7b684b30377e
minimaxChatCompletionProPath = "/v1/text/chatcompletion_pro" minimaxChatCompletionProPath = "/v1/text/chatcompletion_pro"
senderTypeUser string = "USER" // 用户发送的内容 senderTypeUser string = "USER" // Content sent by the user.
senderTypeBot string = "BOT" // 模型生成的内容 senderTypeBot string = "BOT" // Content generated by the model.
// 默认机器人设置 // Default bot settings.
defaultBotName string = "MM智能助理" defaultBotName string = "MM智能助理"
defaultBotSettingContent string = "MM智能助理是一款由MiniMax自研的没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司一直致力于进行大模型相关的研究。" defaultBotSettingContent string = "MM智能助理是一款由MiniMax自研的没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司一直致力于进行大模型相关的研究。"
defaultSenderName string = "小明" defaultSenderName string = "小明"
) )
// chatCompletionProModels 这些模型对应接口为ChatCompletion Pro
var chatCompletionProModels = map[string]struct{}{
"abab6.5-chat": {},
"abab6.5s-chat": {},
"abab5.5s-chat": {},
"abab5.5-chat": {},
}
type minimaxProviderInitializer struct { type minimaxProviderInitializer struct {
} }
func (m *minimaxProviderInitializer) ValidateConfig(config ProviderConfig) error { func (m *minimaxProviderInitializer) ValidateConfig(config ProviderConfig) error {
// 如果存在模型对应接口为ChatCompletion Pro必须配置minimaxGroupId // If using the chat completion Pro API, a group ID must be set.
if len(config.modelMapping) > 0 && config.minimaxGroupId == "" { if minimaxApiTypePro == config.minimaxApiType && config.minimaxGroupId == "" {
for _, minimaxModel := range config.modelMapping { return errors.New(fmt.Sprintf("missing minimaxGroupId in provider config when minimaxApiType is %s", minimaxApiTypePro))
if _, exists := chatCompletionProModels[minimaxModel]; exists {
return errors.New(fmt.Sprintf("missing minimaxGroupId in provider config when %s model is provided", minimaxModel))
}
}
} }
if config.apiTokens == nil || len(config.apiTokens) == 0 { if config.apiTokens == nil || len(config.apiTokens) == 0 {
return errors.New("no apiToken found in provider config") return errors.New("no apiToken found in provider config")
@@ -94,23 +84,11 @@ func (m *minimaxProvider) OnRequestBody(ctx wrapper.HttpContext, apiName ApiName
if apiName != ApiNameChatCompletion { if apiName != ApiNameChatCompletion {
return types.ActionContinue, errUnsupportedApiName return types.ActionContinue, errUnsupportedApiName
} }
// 解析并映射模型,设置上下文 if minimaxApiTypePro == m.config.minimaxApiType {
model, err := m.parseModel(body) // Use chat completion Pro API.
if err != nil {
return types.ActionContinue, err
}
ctx.SetContext(ctxKeyOriginalRequestModel, model)
mappedModel := getMappedModel(model, m.config.modelMapping, log)
if mappedModel == "" {
return types.ActionContinue, errors.New("model becomes empty after applying the configured mapping")
}
ctx.SetContext(ctxKeyFinalRequestModel, mappedModel)
_, ok := chatCompletionProModels[mappedModel]
if ok {
// 使用ChatCompletion Pro接口
return m.handleRequestBodyByChatCompletionPro(body, log) return m.handleRequestBodyByChatCompletionPro(body, log)
} else { } else {
// 使用ChatCompletion v2接口 // Use chat completion V2 API.
return m.config.handleRequestBody(m, m.contextCache, ctx, apiName, body, log) return m.config.handleRequestBody(m, m.contextCache, ctx, apiName, body, log)
} }
} }
@@ -119,14 +97,14 @@ func (m *minimaxProvider) TransformRequestBodyHeaders(ctx wrapper.HttpContext, a
return m.handleRequestBodyByChatCompletionV2(body, headers, log) return m.handleRequestBodyByChatCompletionV2(body, headers, log)
} }
// handleRequestBodyByChatCompletionPro 使用ChatCompletion Pro接口处理请求体 // handleRequestBodyByChatCompletionPro processes the request body using the chat completion Pro API.
func (m *minimaxProvider) handleRequestBodyByChatCompletionPro(body []byte, log wrapper.Log) (types.Action, error) { func (m *minimaxProvider) handleRequestBodyByChatCompletionPro(body []byte, log wrapper.Log) (types.Action, error) {
request := &chatCompletionRequest{} request := &chatCompletionRequest{}
if err := decodeChatCompletionRequest(body, request); err != nil { if err := decodeChatCompletionRequest(body, request); err != nil {
return types.ActionContinue, err return types.ActionContinue, err
} }
// 映射模型重写requestPath // Map the model and rewrite the request path.
request.Model = getMappedModel(request.Model, m.config.modelMapping, log) request.Model = getMappedModel(request.Model, m.config.modelMapping, log)
_ = util.OverwriteRequestPath(fmt.Sprintf("%s?GroupId=%s", minimaxChatCompletionProPath, m.config.minimaxGroupId)) _ = util.OverwriteRequestPath(fmt.Sprintf("%s?GroupId=%s", minimaxChatCompletionProPath, m.config.minimaxGroupId))
@@ -143,9 +121,9 @@ func (m *minimaxProvider) handleRequestBodyByChatCompletionPro(body []byte, log
log.Errorf("failed to load context file: %v", err) log.Errorf("failed to load context file: %v", err)
util.ErrorHandler("ai-proxy.minimax.load_ctx_failed", fmt.Errorf("failed to load context file: %v", err)) util.ErrorHandler("ai-proxy.minimax.load_ctx_failed", fmt.Errorf("failed to load context file: %v", err))
} }
// 由于 minimaxChatCompletionV2(格式和 OpenAI 一致)和 minimaxChatCompletionPro(格式和 OpenAI 不一致)中 insertHttpContextMessage 的逻辑不同,无法做到同一个 provider 统一 // Since minimaxChatCompletionV2 (format consistent with OpenAI) and minimaxChatCompletionPro (different format from OpenAI) have different logic for insertHttpContextMessage, we cannot unify them within one provider.
// 因此对于 minimaxChatCompletionPro 需要手动处理 context 消息 // For minimaxChatCompletionPro, we need to manually handle context messages.
// minimaxChatCompletionV2 交给默认的 defaultInsertHttpContextMessage 方法插入 context 消息 // minimaxChatCompletionV2 uses the default defaultInsertHttpContextMessage method to insert context messages.
minimaxRequest := m.buildMinimaxChatCompletionV2Request(request, content) minimaxRequest := m.buildMinimaxChatCompletionV2Request(request, content)
if err := replaceJsonRequestBody(minimaxRequest, log); err != nil { if err := replaceJsonRequestBody(minimaxRequest, log); err != nil {
util.ErrorHandler("ai-proxy.minimax.insert_ctx_failed", fmt.Errorf("failed to replace Request body: %v", err)) util.ErrorHandler("ai-proxy.minimax.insert_ctx_failed", fmt.Errorf("failed to replace Request body: %v", err))
@@ -157,54 +135,45 @@ func (m *minimaxProvider) handleRequestBodyByChatCompletionPro(body []byte, log
return types.ActionContinue, err return types.ActionContinue, err
} }
// handleRequestBodyByChatCompletionV2 使用ChatCompletion v2接口处理请求体 // handleRequestBodyByChatCompletionV2 processes the request body using the chat completion V2 API.
func (m *minimaxProvider) handleRequestBodyByChatCompletionV2(body []byte, headers http.Header, log wrapper.Log) ([]byte, error) { func (m *minimaxProvider) handleRequestBodyByChatCompletionV2(body []byte, headers http.Header, log wrapper.Log) ([]byte, error) {
request := &chatCompletionRequest{}
if err := decodeChatCompletionRequest(body, request); err != nil {
return nil, err
}
// 映射模型重写requestPath
request.Model = getMappedModel(request.Model, m.config.modelMapping, log)
util.OverwriteRequestPathHeader(headers, minimaxChatCompletionV2Path) util.OverwriteRequestPathHeader(headers, minimaxChatCompletionV2Path)
return body, nil rawModel := gjson.GetBytes(body, "model").String()
mappedModel := getMappedModel(rawModel, m.config.modelMapping, log)
return sjson.SetBytes(body, "model", mappedModel)
} }
func (m *minimaxProvider) OnResponseHeaders(ctx wrapper.HttpContext, apiName ApiName, log wrapper.Log) (types.Action, error) { func (m *minimaxProvider) OnResponseHeaders(ctx wrapper.HttpContext, apiName ApiName, log wrapper.Log) (types.Action, error) {
// 使用minimax接口协议,跳过OnStreamingResponseBody()OnResponseBody() // Skip OnStreamingResponseBody() and OnResponseBody() when using original protocol.
if m.config.protocol == protocolOriginal { if m.config.protocol == protocolOriginal {
ctx.DontReadResponseBody() ctx.DontReadResponseBody()
return types.ActionContinue, nil return types.ActionContinue, nil
} }
// 模型对应接口为ChatCompletion v2,跳过OnStreamingResponseBody()OnResponseBody() // Skip OnStreamingResponseBody() and OnResponseBody() when the model corresponds to the chat completion V2 interface.
model := ctx.GetStringContext(ctxKeyFinalRequestModel, "") if minimaxApiTypePro != m.config.minimaxApiType {
if model != "" { ctx.DontReadResponseBody()
_, ok := chatCompletionProModels[model] return types.ActionContinue, nil
if !ok {
ctx.DontReadResponseBody()
return types.ActionContinue, nil
}
} }
_ = proxywasm.RemoveHttpResponseHeader("Content-Length") _ = proxywasm.RemoveHttpResponseHeader("Content-Length")
return types.ActionContinue, nil return types.ActionContinue, nil
} }
// OnStreamingResponseBody 只处理使用OpenAI协议 且 模型对应接口为ChatCompletion Pro的流式响应 // OnStreamingResponseBody handles streaming response chunks from the Minimax service only for requests using the OpenAI protocol and corresponding to the chat completion Pro API.
func (m *minimaxProvider) OnStreamingResponseBody(ctx wrapper.HttpContext, name ApiName, chunk []byte, isLastChunk bool, log wrapper.Log) ([]byte, error) { func (m *minimaxProvider) OnStreamingResponseBody(ctx wrapper.HttpContext, name ApiName, chunk []byte, isLastChunk bool, log wrapper.Log) ([]byte, error) {
if isLastChunk || len(chunk) == 0 { if isLastChunk || len(chunk) == 0 {
return nil, nil return nil, nil
} }
// sample event response: // Sample event response:
// data: {"created":1689747645,"model":"abab6.5s-chat","reply":"","choices":[{"messages":[{"sender_type":"BOT","sender_name":"MM智能助理","text":"am from China."}]}],"output_sensitive":false} // data: {"created":1689747645,"model":"abab6.5s-chat","reply":"","choices":[{"messages":[{"sender_type":"BOT","sender_name":"MM智能助理","text":"am from China."}]}],"output_sensitive":false}
// sample end event response: // Sample end event response:
// data: {"created":1689747645,"model":"abab6.5s-chat","reply":"I am from China.","choices":[{"finish_reason":"stop","messages":[{"sender_type":"BOT","sender_name":"MM智能助理","text":"I am from China."}]}],"usage":{"total_tokens":187},"input_sensitive":false,"output_sensitive":false,"id":"0106b3bc9fd844a9f3de1aa06004e2ab","base_resp":{"status_code":0,"status_msg":""}} // data: {"created":1689747645,"model":"abab6.5s-chat","reply":"I am from China.","choices":[{"finish_reason":"stop","messages":[{"sender_type":"BOT","sender_name":"MM智能助理","text":"I am from China."}]}],"usage":{"total_tokens":187},"input_sensitive":false,"output_sensitive":false,"id":"0106b3bc9fd844a9f3de1aa06004e2ab","base_resp":{"status_code":0,"status_msg":""}}
responseBuilder := &strings.Builder{} responseBuilder := &strings.Builder{}
lines := strings.Split(string(chunk), "\n") lines := strings.Split(string(chunk), "\n")
for _, data := range lines { for _, data := range lines {
if len(data) < 6 { if len(data) < 6 {
// ignore blank line or wrong format // Ignore blank line or improperly formatted lines.
continue continue
} }
data = data[6:] data = data[6:]
@@ -226,7 +195,7 @@ func (m *minimaxProvider) OnStreamingResponseBody(ctx wrapper.HttpContext, name
return []byte(modifiedResponseChunk), nil return []byte(modifiedResponseChunk), nil
} }
// OnResponseBody 只处理使用OpenAI协议 且 模型对应接口为ChatCompletion Pro的流式响应 // OnResponseBody handles the final response body from the Minimax service only for requests using the OpenAI protocol and corresponding to the chat completion Pro API.
func (m *minimaxProvider) OnResponseBody(ctx wrapper.HttpContext, apiName ApiName, body []byte, log wrapper.Log) (types.Action, error) { func (m *minimaxProvider) OnResponseBody(ctx wrapper.HttpContext, apiName ApiName, body []byte, log wrapper.Log) (types.Action, error) {
minimaxResp := &minimaxChatCompletionV2Resp{} minimaxResp := &minimaxChatCompletionV2Resp{}
if err := json.Unmarshal(body, minimaxResp); err != nil { if err := json.Unmarshal(body, minimaxResp); err != nil {
@@ -239,39 +208,39 @@ func (m *minimaxProvider) OnResponseBody(ctx wrapper.HttpContext, apiName ApiNam
return types.ActionContinue, replaceJsonResponseBody(response, log) return types.ActionContinue, replaceJsonResponseBody(response, log)
} }
// minimaxChatCompletionV2Request 表示ChatCompletion V2请求的结构体 // minimaxChatCompletionV2Request represents the structure of a chat completion V2 request.
type minimaxChatCompletionV2Request struct { type minimaxChatCompletionV2Request struct {
Model string `json:"model"` Model string `json:"model"`
Stream bool `json:"stream,omitempty"` Stream bool `json:"stream,omitempty"`
TokensToGenerate int64 `json:"tokens_to_generate,omitempty"` TokensToGenerate int64 `json:"tokens_to_generate,omitempty"`
Temperature float64 `json:"temperature,omitempty"` Temperature float64 `json:"temperature,omitempty"`
TopP float64 `json:"top_p,omitempty"` TopP float64 `json:"top_p,omitempty"`
MaskSensitiveInfo bool `json:"mask_sensitive_info"` // 是否开启隐私信息打码,默认true MaskSensitiveInfo bool `json:"mask_sensitive_info"` // Whether to mask sensitive information, defaults to true.
Messages []minimaxMessage `json:"messages"` Messages []minimaxMessage `json:"messages"`
BotSettings []minimaxBotSetting `json:"bot_setting"` BotSettings []minimaxBotSetting `json:"bot_setting"`
ReplyConstraints minimaxReplyConstraints `json:"reply_constraints"` ReplyConstraints minimaxReplyConstraints `json:"reply_constraints"`
} }
// minimaxMessage 表示对话中的消息 // minimaxMessage represents a message in the conversation.
type minimaxMessage struct { type minimaxMessage struct {
SenderType string `json:"sender_type"` SenderType string `json:"sender_type"`
SenderName string `json:"sender_name"` SenderName string `json:"sender_name"`
Text string `json:"text"` Text string `json:"text"`
} }
// minimaxBotSetting 表示机器人的设置 // minimaxBotSetting represents the bot's settings.
type minimaxBotSetting struct { type minimaxBotSetting struct {
BotName string `json:"bot_name"` BotName string `json:"bot_name"`
Content string `json:"content"` Content string `json:"content"`
} }
// minimaxReplyConstraints 表示模型回复要求 // minimaxReplyConstraints represents requirements for model replies.
type minimaxReplyConstraints struct { type minimaxReplyConstraints struct {
SenderType string `json:"sender_type"` SenderType string `json:"sender_type"`
SenderName string `json:"sender_name"` SenderName string `json:"sender_name"`
} }
// minimaxChatCompletionV2Resp Minimax Chat Completion V2响应结构体 // minimaxChatCompletionV2Resp represents the structure of a Minimax Chat Completion V2 response.
type minimaxChatCompletionV2Resp struct { type minimaxChatCompletionV2Resp struct {
Created int64 `json:"created"` Created int64 `json:"created"`
Model string `json:"model"` Model string `json:"model"`
@@ -286,20 +255,20 @@ type minimaxChatCompletionV2Resp struct {
BaseResp minimaxBaseResp `json:"base_resp"` BaseResp minimaxBaseResp `json:"base_resp"`
} }
// minimaxBaseResp 包含错误状态码和详情 // minimaxBaseResp contains error status code and details.
type minimaxBaseResp struct { type minimaxBaseResp struct {
StatusCode int64 `json:"status_code"` StatusCode int64 `json:"status_code"`
StatusMsg string `json:"status_msg"` StatusMsg string `json:"status_msg"`
} }
// minimaxChoice 结果选项 // minimaxChoice represents a result option.
type minimaxChoice struct { type minimaxChoice struct {
Messages []minimaxMessage `json:"messages"` Messages []minimaxMessage `json:"messages"`
Index int64 `json:"index"` Index int64 `json:"index"`
FinishReason string `json:"finish_reason"` FinishReason string `json:"finish_reason"`
} }
// minimaxUsage 令牌使用情况 // minimaxUsage represents token usage statistics.
type minimaxUsage struct { type minimaxUsage struct {
TotalTokens int64 `json:"total_tokens"` TotalTokens int64 `json:"total_tokens"`
} }

View File

@@ -206,8 +206,11 @@ type ProviderConfig struct {
// @Title zh-CN hunyuan api id for authorization // @Title zh-CN hunyuan api id for authorization
// @Description zh-CN 仅适用于Hun Yuan AI服务鉴权 // @Description zh-CN 仅适用于Hun Yuan AI服务鉴权
hunyuanAuthId string `required:"false" yaml:"hunyuanAuthId" json:"hunyuanAuthId"` hunyuanAuthId string `required:"false" yaml:"hunyuanAuthId" json:"hunyuanAuthId"`
// @Title zh-CN minimax API type
// @Description zh-CN 仅适用于 minimax 服务。minimax API 类型v2 和 pro 中选填一项,默认值为 v2
minimaxApiType string `required:"false" yaml:"minimaxApiType" json:"minimaxApiType"`
// @Title zh-CN minimax group id // @Title zh-CN minimax group id
// @Description zh-CN 仅适用于minimax使用ChatCompletion Pro接口的模型 // @Description zh-CN 仅适用于 minimax 服务。minimax API 类型为 pro 时必填
minimaxGroupId string `required:"false" yaml:"minimaxGroupId" json:"minimaxGroupId"` minimaxGroupId string `required:"false" yaml:"minimaxGroupId" json:"minimaxGroupId"`
// @Title zh-CN 模型名称映射表 // @Title zh-CN 模型名称映射表
// @Description zh-CN 用于将请求中的模型名称映射为目标AI服务商支持的模型名称。支持通过“*”来配置全局映射 // @Description zh-CN 用于将请求中的模型名称映射为目标AI服务商支持的模型名称。支持通过“*”来配置全局映射
@@ -303,6 +306,7 @@ func (c *ProviderConfig) FromJson(json gjson.Result) {
c.claudeVersion = json.Get("claudeVersion").String() c.claudeVersion = json.Get("claudeVersion").String()
c.hunyuanAuthId = json.Get("hunyuanAuthId").String() c.hunyuanAuthId = json.Get("hunyuanAuthId").String()
c.hunyuanAuthKey = json.Get("hunyuanAuthKey").String() c.hunyuanAuthKey = json.Get("hunyuanAuthKey").String()
c.minimaxApiType = json.Get("minimaxApiType").String()
c.minimaxGroupId = json.Get("minimaxGroupId").String() c.minimaxGroupId = json.Get("minimaxGroupId").String()
c.cloudflareAccountId = json.Get("cloudflareAccountId").String() c.cloudflareAccountId = json.Get("cloudflareAccountId").String()
if c.typ == providerTypeGemini { if c.typ == providerTypeGemini {