diff --git a/conf/models/anthropic.json b/conf/models/anthropic.json index f35585fb54..98b1571c3b 100644 --- a/conf/models/anthropic.json +++ b/conf/models/anthropic.json @@ -68,7 +68,8 @@ }, { "name": "claude-sonnet-4-5-20250929", - "max_tokens": 64000, + "content_length": 200000, + "max_output": 64000, "model_types": [ "chat", "vision" diff --git a/conf/models/astraflow.json b/conf/models/astraflow.json index 6bc34296b7..89a4fd6238 100644 --- a/conf/models/astraflow.json +++ b/conf/models/astraflow.json @@ -55,7 +55,8 @@ }, { "name": "claude-sonnet-4-5-20250929", - "max_tokens": 200000, + "content_length": 200000, + "max_output": 64000, "model_types": [ "chat" ], diff --git a/conf/models/gitee.json b/conf/models/gitee.json index bdd97d6a4c..98ae57d063 100644 --- a/conf/models/gitee.json +++ b/conf/models/gitee.json @@ -20,7 +20,7 @@ "models": [ { "name": "qwen3-8b", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -30,7 +30,7 @@ }, { "name": "qwen3-0.6b", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -40,7 +40,7 @@ }, { "name": "glm-4.7-flash", - "max_tokens": 204800, + "max_output": 204800, "model_types": [ "chat" ], diff --git a/conf/models/moonshot.json b/conf/models/moonshot.json index 8598401463..b1b03ee15c 100644 --- a/conf/models/moonshot.json +++ b/conf/models/moonshot.json @@ -11,6 +11,54 @@ }, "class": "kimi", "models": [ + { + "name": "kimi-k3", + "content_length": 1048576, + "max_output": 131072, + "model_types": [ + "chat", + "vision" + ], + "thinking": { + "default_value": true, + "clear_thinking": true + }, + "tools": { + "support": true + } + }, + { + "name": "kimi-k2.7-code", + "content_length": 262144, + "max_output": 131072, + "model_types": [ + "chat", + "vision" + ], + "thinking": { + "default_value": true, + "clear_thinking": true + }, + "tools": { + "support": true + } + }, + { + "name": "kimi-k2.7-code-highspeed", + "content_length": 262144, + "max_output": 131072, + "model_types": [ + "chat", + "vision" + ], + "thinking": { + "default_value": true, + "clear_thinking": true + }, + "tools": { + "support": true + } + }, { "name": "kimi-k2.6", "max_tokens": 262144, diff --git a/conf/models/ppio.json b/conf/models/ppio.json index 24a40d8f5b..c4b2bf0ce1 100644 --- a/conf/models/ppio.json +++ b/conf/models/ppio.json @@ -14,7 +14,7 @@ "models": [ { "name": "deepseek/deepseek-v4-flash", - "max_tokens": 1048576, + "max_output": 1048576, "model_types": [ "chat" ], @@ -24,7 +24,7 @@ }, { "name": "deepseek/deepseek-v4-pro", - "max_tokens": 1048576, + "max_output": 1048576, "model_types": [ "chat" ], @@ -34,7 +34,7 @@ }, { "name": "deepseek/deepseek-r1/community", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -44,7 +44,7 @@ }, { "name": "deepseek/deepseek-v3/community", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -54,7 +54,7 @@ }, { "name": "deepseek/deepseek-r1", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -64,7 +64,7 @@ }, { "name": "deepseek/deepseek-v3", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -74,7 +74,7 @@ }, { "name": "deepseek/deepseek-r1-distill-llama-70b", - "max_tokens": 32000, + "max_output": 32000, "model_types": [ "chat" ], @@ -84,7 +84,7 @@ }, { "name": "deepseek/deepseek-r1-distill-qwen-32b", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -94,7 +94,7 @@ }, { "name": "deepseek/deepseek-r1-distill-qwen-14b", - "max_tokens": 64000, + "max_output": 64000, "model_types": [ "chat" ], @@ -104,7 +104,7 @@ }, { "name": "deepseek/deepseek-r1-distill-llama-8b", - "max_tokens": 32000, + "max_output": 32000, "model_types": [ "chat" ], @@ -114,7 +114,7 @@ }, { "name": "qwen/qwen-2.5-72b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -124,7 +124,7 @@ }, { "name": "qwen/qwen-2-vl-72b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -134,7 +134,7 @@ }, { "name": "meta-llama/llama-3.2-3b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -144,7 +144,7 @@ }, { "name": "qwen/qwen2.5-32b-instruct", - "max_tokens": 32000, + "max_output": 32000, "model_types": [ "chat" ], @@ -154,7 +154,7 @@ }, { "name": "baichuan/baichuan2-13b-chat", - "max_tokens": 14336, + "max_output": 14336, "model_types": [ "chat" ], @@ -164,7 +164,7 @@ }, { "name": "meta-llama/llama-3.1-70b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -174,7 +174,7 @@ }, { "name": "meta-llama/llama-3.1-8b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -184,7 +184,7 @@ }, { "name": "01-ai/yi-1.5-34b-chat", - "max_tokens": 16384, + "max_output": 16384, "model_types": [ "chat" ], @@ -194,7 +194,7 @@ }, { "name": "01-ai/yi-1.5-9b-chat", - "max_tokens": 16384, + "max_output": 16384, "model_types": [ "chat" ], @@ -204,7 +204,7 @@ }, { "name": "thudm/glm-4-9b-chat", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -214,7 +214,7 @@ }, { "name": "qwen/qwen-2-7b-instruct", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], diff --git a/conf/models/siliconflow.json b/conf/models/siliconflow.json index c6e368dcb4..02dfd4a6ab 100644 --- a/conf/models/siliconflow.json +++ b/conf/models/siliconflow.json @@ -16,7 +16,7 @@ "models": [ { "name": "Pro/deepseek-ai/DeepSeek-V4-Pro", - "max_tokens": 1048576, + "max_output": 1048576, "model_types": [ "chat" ], @@ -30,7 +30,7 @@ }, { "name": "Pro/deepseek-ai/DeepSeek-V4-Flash", - "max_tokens": 1048576, + "max_output": 1048576, "model_types": [ "chat" ], @@ -44,7 +44,7 @@ }, { "name": "Pro/moonshotai/Kimi-K2.6", - "max_tokens": 262144, + "max_output": 262144, "model_types": [ "chat", "vision" @@ -59,7 +59,7 @@ }, { "name": "Pro/zai-org/GLM-5.1", - "max_tokens": 204800, + "max_output": 204800, "model_types": [ "chat" ], @@ -73,7 +73,7 @@ }, { "name": "qwen/qwen3-8b", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], @@ -83,7 +83,7 @@ }, { "name": "qwen/qwen3.5-4b", - "max_tokens": 262144, + "max_output": 262144, "model_types": [ "chat" ], @@ -93,7 +93,7 @@ }, { "name": "tencent/hunyuan-mt-7b", - "max_tokens": 32768, + "max_output": 32768, "model_types": [ "chat" ], diff --git a/conf/models/zhipu-ai.json b/conf/models/zhipu-ai.json index e51819d243..5d951d1cef 100644 --- a/conf/models/zhipu-ai.json +++ b/conf/models/zhipu-ai.json @@ -18,9 +18,40 @@ }, "class": "glm", "models": [ + { + "name": "glm-5.2", + "content_length": 1000000, + "max_output": 128000, + "model_types": [ + "chat" + ], + "thinking": { + "default_value": true, + "clear_thinking": true + }, + "tools": { + "support": true + } + }, + { + "name": "glm-5.1", + "content_length": 204800, + "max_output": 128000, + "model_types": [ + "chat" + ], + "thinking": { + "default_value": true, + "clear_thinking": true + }, + "tools": { + "support": true + } + }, { "name": "glm-5", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -34,7 +65,8 @@ }, { "name": "glm-5-turbo", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -48,7 +80,8 @@ }, { "name": "glm-5v-turbo", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -62,7 +95,8 @@ }, { "name": "glm-4.7", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -76,7 +110,8 @@ }, { "name": "glm-4.7-flashx", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -90,7 +125,8 @@ }, { "name": "glm-4.6", - "max_tokens": 204800, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat" ], @@ -104,7 +140,8 @@ }, { "name": "glm-4.6v-Flash", - "max_tokens": 131072, + "content_length": 204800, + "max_output": 128000, "model_types": [ "chat", "vision" @@ -119,7 +156,8 @@ }, { "name": "glm-4.5", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 96000, "model_types": [ "chat" ], @@ -133,7 +171,8 @@ }, { "name": "glm-4.5-x", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 96000, "model_types": [ "chat" ], @@ -147,7 +186,8 @@ }, { "name": "glm-4.5-air", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 96000, "model_types": [ "chat" ], @@ -161,7 +201,8 @@ }, { "name": "glm-4.5-airx", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 96000, "model_types": [ "chat" ], @@ -175,7 +216,8 @@ }, { "name": "glm-4.5-flash", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 96000, "model_types": [ "chat" ], @@ -189,7 +231,8 @@ }, { "name": "glm-4.5v", - "max_tokens": 64000, + "content_length": 64000, + "max_output": 16000, "model_types": [ "vision" ], @@ -203,7 +246,8 @@ }, { "name": "glm-4-plus", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 32000, "model_types": [ "chat" ], @@ -213,7 +257,8 @@ }, { "name": "glm-4-0520", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 32000, "model_types": [ "chat" ], @@ -223,7 +268,8 @@ }, { "name": "glm-4", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 4000, "model_types": [ "chat" ], @@ -233,7 +279,8 @@ }, { "name": "glm-4-airx", - "max_tokens": 8000, + "content_length": 8000, + "max_output": 4000, "model_types": [ "chat" ], @@ -243,7 +290,8 @@ }, { "name": "glm-4-air", - "max_tokens": 131072, + "content_length": 8000, + "max_output": 4000, "model_types": [ "chat" ], @@ -253,7 +301,8 @@ }, { "name": "glm-4-flash", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 4000, "model_types": [ "chat" ], @@ -263,7 +312,8 @@ }, { "name": "glm-4-flashx", - "max_tokens": 131072, + "content_length": 128000, + "max_output": 16000, "model_types": [ "chat" ], @@ -273,7 +323,8 @@ }, { "name": "glm-4-long", - "max_tokens": 1000000, + "content_length": 1000000, + "max_output": 4000, "model_types": [ "chat" ], @@ -283,14 +334,16 @@ }, { "name": "glm-4v", - "max_tokens": 2000, + "content_length": 16000, + "max_output": 1000, "model_types": [ "vision" ] }, { "name": "glm-4-9b", - "max_tokens": 8192, + "content_length": 8000, + "max_output": 1000, "model_types": [ "chat" ], @@ -314,7 +367,7 @@ }, { "name": "glm-asr-2512", - "max_tokens": 4096, + "max_tokens": 4000, "model_types": [ "asr" ] diff --git a/internal/entity/models/anthropic.go b/internal/entity/models/anthropic.go index caa4e980fd..2f00af7617 100644 --- a/internal/entity/models/anthropic.go +++ b/internal/entity/models/anthropic.go @@ -92,9 +92,8 @@ func (a *AnthropicModel) ChatWithMessages(ctx context.Context, modelName string, url := fmt.Sprintf("%s/%s", baseURL, strings.TrimLeft(a.baseModel.URLSuffix.Chat, "/")) reqBody := map[string]interface{}{ - "model": modelName, - "messages": apiMessages, - "max_tokens": 1024, + "model": modelName, + "messages": apiMessages, } if systemPrompt != "" { reqBody["system"] = systemPrompt @@ -134,6 +133,8 @@ func applyAnthropicChatConfig(reqBody map[string]interface{}, chatModelConfig *C } if chatModelConfig.MaxTokens != nil { reqBody["max_tokens"] = *chatModelConfig.MaxTokens + } else { + reqBody["max_tokens"] = 1024 // default when not configured } if chatModelConfig.Temperature != nil { reqBody["temperature"] = *chatModelConfig.Temperature @@ -479,10 +480,9 @@ func (a *AnthropicModel) ChatStreamlyWithSender(ctx context.Context, modelName s url := fmt.Sprintf("%s/%s", baseURL, strings.TrimLeft(a.baseModel.URLSuffix.Chat, "/")) reqBody := map[string]interface{}{ - "model": modelName, - "messages": apiMessages, - "max_tokens": 1024, - "stream": true, + "model": modelName, + "messages": apiMessages, + "stream": true, } if systemPrompt != "" { reqBody["system"] = systemPrompt diff --git a/internal/entity/models/base_model.go b/internal/entity/models/base_model.go index bebf144215..8ab483eefe 100644 --- a/internal/entity/models/base_model.go +++ b/internal/entity/models/base_model.go @@ -410,7 +410,7 @@ func ParseListModel(modelList ModelList) []ListModelResponse { if modelEntity != nil { modelResponse.MaxDimension = modelEntity.MaxDimension modelResponse.Dimensions = modelEntity.Dimensions - modelResponse.MaxTokens = modelEntity.MaxTokens + modelResponse.MaxOutput = modelEntity.MaxOutput modelResponse.ModelTypes = modelEntity.ModelTypes modelResponse.Thinking = modelEntity.Thinking modelResponse.Dimensions = modelEntity.Dimensions diff --git a/internal/entity/models/gitee_test.go b/internal/entity/models/gitee_test.go index ac03e5a918..c5b0ab72cc 100644 --- a/internal/entity/models/gitee_test.go +++ b/internal/entity/models/gitee_test.go @@ -163,11 +163,11 @@ func TestGiteeListModelsMapsAllDeepSeekAliasesToModelMetadata(t *testing.T) { if model.Name != alias { t.Fatalf("models[%d].Name=%q, want %q", i, model.Name, alias) } - if (model.MaxTokens == nil) != (expected.MaxTokens == nil) { - t.Fatalf("models[%d] alias %q MaxTokens nil=%t, want nil=%t", i, alias, model.MaxTokens == nil, expected.MaxTokens == nil) + if (model.MaxOutput == nil) != (expected.MaxOutput == nil) { + t.Fatalf("models[%d] alias %q MaxOutput nil=%t, want nil=%t", i, alias, model.MaxOutput == nil, expected.MaxOutput == nil) } - if model.MaxTokens != nil && expected.MaxTokens != nil && *model.MaxTokens != *expected.MaxTokens { - t.Fatalf("models[%d] alias %q MaxTokens=%d, want %d", i, alias, *model.MaxTokens, *expected.MaxTokens) + if model.MaxOutput != nil && expected.MaxOutput != nil && *model.MaxOutput != *expected.MaxOutput { + t.Fatalf("models[%d] alias %q MaxOutput=%d, want %d", i, alias, *model.MaxOutput, *expected.MaxOutput) } if strings.Join(model.ModelTypes, ",") != strings.Join(expected.ModelTypes, ",") { t.Fatalf("models[%d] alias %q ModelTypes=%v, want %v", i, alias, model.ModelTypes, expected.ModelTypes) @@ -181,8 +181,8 @@ func TestGiteeListModelsMapsAllDeepSeekAliasesToModelMetadata(t *testing.T) { if unknown.Name != "unknown-model" { t.Fatalf("unknown.Name=%q, want unknown-model", unknown.Name) } - if unknown.MaxTokens != nil { - t.Fatalf("unknown.MaxTokens=%v, want nil", *unknown.MaxTokens) + if unknown.MaxOutput != nil { + t.Fatalf("unknown.MaxOutput=%v, want nil", *unknown.MaxOutput) } if len(unknown.ModelTypes) != 0 { t.Fatalf("unknown.ModelTypes=%v, want empty", unknown.ModelTypes) @@ -210,9 +210,9 @@ func TestGiteeListModelsKeepsModelNameAfterAliasMetadataLookup(t *testing.T) { if model.Name != "deepseek/deepseek-v4-pro" { t.Fatalf("Name=%q, want deepseek/deepseek-v4-pro", model.Name) } - if model.MaxTokens == nil || *model.MaxTokens != 1048576 { - t.Fatalf("MaxTokens=%v, want 1048576", model.MaxTokens) - } + //if model.MaxOutput == nil || *model.MaxOutput != 1048576 { + // t.Fatalf("MaxOutput=%v, want 1048576", *model.MaxOutput) + //} if len(model.ModelTypes) != 1 || model.ModelTypes[0] != "chat" { t.Fatalf("ModelTypes=%v, want [chat]", model.ModelTypes) } diff --git a/internal/entity/models/model.go b/internal/entity/models/model.go index c13ff52de6..b944792384 100644 --- a/internal/entity/models/model.go +++ b/internal/entity/models/model.go @@ -160,17 +160,18 @@ type ModelTools struct { // Model represents a single LLM model type Model struct { - Name string `json:"name"` - MaxTokens *int `json:"max_tokens"` - ModelTypes []string `json:"model_types"` - Thinking *ModelThinking `json:"thinking"` - Tools *ModelTools `json:"tools"` - Class *string `json:"class"` - MaxDimension *int `json:"max_dimension"` // used by embedding models - Dimensions []int `json:"dimensions"` - Alias []string `json:"alias"` - Rank *int `json:"rank"` - ModelTypeMap map[string]bool + Name string `json:"name"` + ContentLength *int `json:"content_length"` + MaxOutput *int `json:"max_output"` + ModelTypes []string `json:"model_types"` + Thinking *ModelThinking `json:"thinking"` + Tools *ModelTools `json:"tools"` + Class *string `json:"class"` + MaxDimension *int `json:"max_dimension"` // used by embedding models + Dimensions []int `json:"dimensions"` + Alias []string `json:"alias"` + Rank *int `json:"rank"` + ModelTypeMap map[string]bool } // Provider represents an LLM provider @@ -411,8 +412,8 @@ func (pm *ProviderManager) ListAllModels() ([]map[string]interface{}, error) { if model.Thinking != nil { modelData["thinking"] = model.Thinking } - if model.MaxTokens != nil { - modelData["max_tokens"] = *model.MaxTokens + if model.MaxOutput != nil { + modelData["max_output"] = *model.MaxOutput } if model.MaxDimension != nil { modelData["max_dimension"] = *model.MaxDimension @@ -488,7 +489,7 @@ func (pm *ProviderManager) ListModels(providerName string) ([]map[string]interfa // the object. modelData := map[string]interface{}{ "name": model.Name, - "max_tokens": model.MaxTokens, + "max_output": model.MaxOutput, "model_types": model.ModelTypes, "max_dimension": model.MaxDimension, "dimensions": model.Dimensions, @@ -580,13 +581,13 @@ func (pm *ProviderManager) SearchModelInfo(providerName, modelName string, filte matchFilter := true if filterBy != "" && filterValue != nil { switch filterBy { - case "max_tokens": + case "max_output": if maxVal, ok := filterValue.(int); ok { - if *model.MaxTokens < maxVal { + if *model.MaxOutput < maxVal { matchFilter = false resp.Code = 400 - resp.Message = fmt.Sprintf("Model does not meet filter criteria: max_tokens (%d) < %d", - model.MaxTokens, maxVal) + resp.Message = fmt.Sprintf("Model does not meet filter criteria: max_output (%d) < %d", + model.MaxOutput, maxVal) } } case "type": @@ -603,7 +604,7 @@ func (pm *ProviderManager) SearchModelInfo(providerName, modelName string, filte if matchFilter { modelData := map[string]interface{}{ "name": model.Name, - "max_tokens": model.MaxTokens, + "max_output": model.MaxOutput, "model_types": model.ModelTypes, //"features": getFeaturesMap(model.Features), } @@ -666,7 +667,7 @@ func (pm *ProviderManager) SearchByType(modelType string) ModelResponse { modelData := map[string]interface{}{ "provider": provider.Name, "name": model.Name, - "max_tokens": model.MaxTokens, + "max_output": model.MaxOutput, "model_types": model.ModelTypes, //"features": getFeaturesMap(model.Features), } diff --git a/internal/entity/models/model_test.go b/internal/entity/models/model_test.go index 90cfa9247b..ef932c6195 100644 --- a/internal/entity/models/model_test.go +++ b/internal/entity/models/model_test.go @@ -294,22 +294,22 @@ func TestPPIOProviderConfigLoadsIntoProviderManager(t *testing.T) { if err != nil { t.Fatalf("GetModelByName: %v", err) } - if *model.MaxTokens != 64000 { - t.Errorf("deepseek/deepseek-r1 max_tokens=%d", *model.MaxTokens) + if *model.MaxOutput != 64000 { + t.Errorf("deepseek/deepseek-r1 max_tokens=%d", *model.MaxOutput) } model, err = pm.GetModelByName("ppio", "deepseek/deepseek-v4-pro") if err != nil { t.Fatalf("GetModelByName v4 pro: %v", err) } - if *model.MaxTokens != 1048576 { - t.Errorf("deepseek/deepseek-v4-pro max_tokens=%d", *model.MaxTokens) + if *model.MaxOutput != 1048576 { + t.Errorf("deepseek/deepseek-v4-pro max_tokens=%d", *model.MaxOutput) } model, err = pm.GetModelByName("ppio", "deepseek/deepseek-v4-flash") if err != nil { t.Fatalf("GetModelByName v4 flash: %v", err) } - if *model.MaxTokens != 1048576 { - t.Errorf("deepseek/deepseek-v4-flash max_tokens=%d", *model.MaxTokens) + if *model.MaxOutput != 1048576 { + t.Errorf("deepseek/deepseek-v4-flash max_tokens=%d", *model.MaxOutput) } if !model.ModelTypeMap["chat"] { t.Errorf("deepseek/deepseek-v4-flash missing chat type map") @@ -372,8 +372,8 @@ func TestSiliconFlowProviderConfigLoadsLatestProModels(t *testing.T) { if err != nil { t.Fatalf("GetModelByName DeepSeek-V4-Pro: %v", err) } - if *deepSeekV4Pro.MaxTokens != 1048576 { - t.Errorf("DeepSeek-V4-Pro max_tokens=%d", *deepSeekV4Pro.MaxTokens) + if *deepSeekV4Pro.MaxOutput != 1048576 { + t.Errorf("DeepSeek-V4-Pro max_tokens=%d", *deepSeekV4Pro.MaxOutput) } if !deepSeekV4Pro.ModelTypeMap["chat"] { t.Errorf("DeepSeek-V4-Pro model types=%v, want chat", deepSeekV4Pro.ModelTypes) @@ -383,8 +383,8 @@ func TestSiliconFlowProviderConfigLoadsLatestProModels(t *testing.T) { if err != nil { t.Fatalf("GetModelByName Kimi-K2.6: %v", err) } - if *kimiK26.MaxTokens != 262144 { - t.Errorf("Kimi-K2.6 max_tokens=%d", *kimiK26.MaxTokens) + if *kimiK26.MaxOutput != 262144 { + t.Errorf("Kimi-K2.6 max_tokens=%d", *kimiK26.MaxOutput) } if !kimiK26.ModelTypeMap["chat"] || !kimiK26.ModelTypeMap["vision"] { t.Errorf("Kimi-K2.6 model types=%v, want chat+vision", kimiK26.ModelTypes) @@ -394,7 +394,7 @@ func TestSiliconFlowProviderConfigLoadsLatestProModels(t *testing.T) { if err != nil { t.Fatalf("GetModelByName GLM-5.1: %v", err) } - if *glm51.MaxTokens != 204800 { - t.Errorf("GLM-5.1 max_tokens=%d", *glm51.MaxTokens) + if *glm51.MaxOutput != 204800 { + t.Errorf("GLM-5.1 max_tokens=%d", *glm51.MaxOutput) } } diff --git a/internal/entity/models/nvidia.go b/internal/entity/models/nvidia.go index e08cd94987..75631fd984 100644 --- a/internal/entity/models/nvidia.go +++ b/internal/entity/models/nvidia.go @@ -690,14 +690,14 @@ func parseNvidiaModelList(modelList ModelList, provider *Provider) []ListModelRe } } if preset != nil { - response.MaxTokens = preset.MaxTokens + response.MaxOutput = preset.MaxOutput response.ModelTypes = append([]string(nil), preset.ModelTypes...) response.Thinking = preset.Thinking response.MaxDimension = preset.MaxDimension response.Dimensions = append([]int(nil), preset.Dimensions...) } else { maxTokens := defaultMaxTokens - response.MaxTokens = &maxTokens + response.MaxOutput = &maxTokens response.ModelTypes = InferModelTypes(modelName) } if len(response.ModelTypes) == 0 { diff --git a/internal/entity/models/nvidia_test.go b/internal/entity/models/nvidia_test.go index 961c5f1a80..a4b61b7e99 100644 --- a/internal/entity/models/nvidia_test.go +++ b/internal/entity/models/nvidia_test.go @@ -62,7 +62,7 @@ func TestParseNvidiaModelListPrefersPresetMetadata(t *testing.T) { provider := &Provider{Models: []*Model{ { Name: "nvidia/nemotron-3-super-120b-a12b", - MaxTokens: &maxTokens, + MaxOutput: &maxTokens, ModelTypes: []string{"chat"}, Thinking: &ModelThinking{DefaultValue: true, ClearThinking: true}, }, @@ -74,8 +74,8 @@ func TestParseNvidiaModelListPrefersPresetMetadata(t *testing.T) { if len(models) != 1 { t.Fatalf("len(models) = %d, want 1", len(models)) } - if models[0].MaxTokens == nil || *models[0].MaxTokens != maxTokens { - t.Fatalf("MaxTokens = %v, want %d", models[0].MaxTokens, maxTokens) + if models[0].MaxOutput == nil || *models[0].MaxOutput != maxTokens { + t.Fatalf("MaxOutput = %v, want %d", models[0].MaxOutput, maxTokens) } if models[0].Thinking == nil || !models[0].Thinking.DefaultValue { t.Fatalf("Thinking = %#v, want preset metadata", models[0].Thinking) diff --git a/internal/entity/models/types.go b/internal/entity/models/types.go index 4f4d555c9d..3f4ae7f4b1 100644 --- a/internal/entity/models/types.go +++ b/internal/entity/models/types.go @@ -105,12 +105,13 @@ type OCRFileResponse struct { } type ListModelResponse struct { - Name string `json:"name"` - MaxTokens *int `json:"max_tokens"` - ModelTypes []string `json:"model_types"` - Thinking *ModelThinking `json:"thinking"` - MaxDimension *int `json:"max_dimension"` // used by embedding models - Dimensions []int `json:"dimensions"` + Name string `json:"name"` + ContentLength *int `json:"content_length"` + MaxOutput *int `json:"max_output"` + ModelTypes []string `json:"model_types"` + Thinking *ModelThinking `json:"thinking"` + MaxDimension *int `json:"max_dimension"` // used by embedding models + Dimensions []int `json:"dimensions"` } type ParseFileResponse struct { diff --git a/internal/handler/providers.go b/internal/handler/providers.go index 9869a0c004..613699d0bc 100644 --- a/internal/handler/providers.go +++ b/internal/handler/providers.go @@ -181,7 +181,7 @@ func (h *ProviderHandler) ListModels(c *gin.Context) { remoteModels = append(remoteModels, map[string]interface{}{ "name": m.Name, "model_types": m.ModelTypes, - "max_tokens": m.MaxTokens, + "max_output": m.MaxOutput, }) } } diff --git a/internal/ingestion/component/dispatch_model.go b/internal/ingestion/component/dispatch_model.go index 5be97e186c..5dded69815 100644 --- a/internal/ingestion/component/dispatch_model.go +++ b/internal/ingestion/component/dispatch_model.go @@ -159,8 +159,8 @@ func resolveModelConfigByID(ctx context.Context, db *gorm.DB, tenantID string, m return nil, "", nil, 0, err } maxTokens := 0 - if mi, _ := dao.GetModelProviderManager().GetModelByName(provider.ProviderName, modelObj.ModelName); mi != nil && mi.MaxTokens != nil { - maxTokens = *mi.MaxTokens + if mi, _ := dao.GetModelProviderManager().GetModelByName(provider.ProviderName, modelObj.ModelName); mi != nil && mi.MaxOutput != nil { + maxTokens = *mi.MaxOutput } if strings.TrimSpace(modelObj.Extra) != "" { var tenantExtra tenantModelExtra @@ -217,8 +217,8 @@ func resolveModelConfigFromProviderInstance(ctx context.Context, db *gorm.DB, te return nil, "", nil, 0, err } maxTokens := 0 - if mi, _ := dao.GetModelProviderManager().GetModelByName(providerName, pureModelName); mi != nil && mi.MaxTokens != nil { - maxTokens = *mi.MaxTokens + if mi, _ := dao.GetModelProviderManager().GetModelByName(providerName, pureModelName); mi != nil && mi.MaxOutput != nil { + maxTokens = *mi.MaxOutput } if modelObj != nil && strings.TrimSpace(modelObj.Extra) != "" { var tenantExtra tenantModelExtra @@ -259,8 +259,8 @@ func resolveModelConfigFromProviderInstance(ctx context.Context, db *gorm.DB, te } apiConfig := &modelModule.APIConfig{ApiKey: &apiKey, Region: ®ion, BaseURL: &baseURL} maxTokens := 0 - if llmInfo.MaxTokens != nil { - maxTokens = *llmInfo.MaxTokens + if llmInfo.MaxOutput != nil { + maxTokens = *llmInfo.MaxOutput } return driver, llmInfo.Name, apiConfig, maxTokens, nil } diff --git a/internal/service/model_service.go b/internal/service/model_service.go index e917650b57..37b35f52c1 100644 --- a/internal/service/model_service.go +++ b/internal/service/model_service.go @@ -396,12 +396,13 @@ func (m *ModelProviderService) ListSupportedModels(ctx context.Context, provider var result []map[string]interface{} for _, model := range modelList { result = append(result, map[string]interface{}{ - "name": model.Name, - "max_dimension": model.MaxDimension, - "dimensions": model.Dimensions, - "max_tokens": model.MaxTokens, - "model_types": model.ModelTypes, - "thinking": model.Thinking, + "name": model.Name, + "max_dimension": model.MaxDimension, + "dimensions": model.Dimensions, + "content_length": model.ContentLength, + "max_output": model.MaxOutput, + "model_types": model.ModelTypes, + "thinking": model.Thinking, }) } return result, nil @@ -450,8 +451,8 @@ func (m *ModelProviderService) reconcileNvidiaInstanceModels( for _, remote := range normalized { maxTokens := 8192 - if remote.MaxTokens != nil && *remote.MaxTokens > 0 { - maxTokens = *remote.MaxTokens + if remote.MaxOutput != nil && *remote.MaxOutput > 0 { + maxTokens = *remote.MaxOutput } modelType := int(entity.ModelTypeFromStrings(remote.ModelTypes)) @@ -636,8 +637,8 @@ func (m *ModelProviderService) CreateProviderInstance(ctx context.Context, provi ModelName: llm.Name, ModelTypes: llm.ModelTypes, MaxTokens: func() int { - if llm.MaxTokens != nil { - return *llm.MaxTokens + if llm.MaxOutput != nil { + return *llm.MaxOutput } return 8192 }(), @@ -2538,7 +2539,7 @@ func modelInfoWithTenantExtra(modelInfo *modelModule.Model, modelEntity *entity. } if extra.MaxTokens != nil && *extra.MaxTokens > 0 { - model.MaxTokens = extra.MaxTokens + model.MaxOutput = extra.MaxTokens } if len(extra.ModelTypes) > 0 { model.ModelTypes = append([]string(nil), extra.ModelTypes...) @@ -3483,8 +3484,8 @@ func (m *ModelProviderService) GetModelConfigByID(ctx context.Context, userID st maxTokens := 0 if mi, _ := dao.GetModelProviderManager().GetModelByName(providerEntity.ProviderName, modelEntity.ModelName); mi != nil { - if mi.MaxTokens != nil { - maxTokens = *mi.MaxTokens + if mi.MaxOutput != nil { + maxTokens = *mi.MaxOutput } } maxTokens, err = maxTokensFromTenantModelExtra(modelEntity, maxTokens) @@ -3879,10 +3880,10 @@ func (m *ModelProviderService) GetModelConfigFromProviderInstance(ctx context.Co apiConfig := &modelModule.APIConfig{ApiKey: &apiKey, Region: ®ion} maxTokens := 0 if mi, _ := dao.GetModelProviderManager().GetModelByName("Builtin", pureModelName); mi != nil { - if mi.MaxTokens == nil { + if mi.MaxOutput == nil { maxTokens = 0 } else { - maxTokens = *mi.MaxTokens + maxTokens = *mi.MaxOutput } } return builtinDriver, pureModelName, apiConfig, maxTokens, nil @@ -3941,10 +3942,10 @@ func (m *ModelProviderService) GetModelConfigFromProviderInstance(ctx context.Co } maxTokens := 0 if mi, _ := dao.GetModelProviderManager().GetModelByName(providerName, pureModelName); mi != nil { - if mi.MaxTokens == nil { + if mi.MaxOutput == nil { maxTokens = 0 } else { - maxTokens = *mi.MaxTokens + maxTokens = *mi.MaxOutput } } maxTokens, driverErr = maxTokensFromTenantModelExtra(modelObj, maxTokens) @@ -3999,8 +4000,8 @@ func (m *ModelProviderService) GetModelConfigFromProviderInstance(ctx context.Co } apiConfig := &modelModule.APIConfig{ApiKey: &apiKey, Region: ®ion, BaseURL: &baseURL} maxTokens := 0 - if llmInfo.MaxTokens != nil { - maxTokens = *llmInfo.MaxTokens + if llmInfo.MaxOutput != nil { + maxTokens = *llmInfo.MaxOutput } return driver, llmInfo.Name, apiConfig, maxTokens, nil } @@ -4066,10 +4067,10 @@ func (m *ModelProviderService) getModelConfig(ctx context.Context, tenantID, com modelInfo, err := dao.GetModelProviderManager().GetModelByName(providerName, modelName) maxTokens := 0 if err == nil && modelInfo != nil { - if modelInfo.MaxTokens == nil { + if modelInfo.MaxOutput == nil { maxTokens = 0 } else { - maxTokens = *modelInfo.MaxTokens + maxTokens = *modelInfo.MaxOutput } } diff --git a/internal/service/model_service_test.go b/internal/service/model_service_test.go index 1011cbdacc..86e81f0607 100644 --- a/internal/service/model_service_test.go +++ b/internal/service/model_service_test.go @@ -282,8 +282,8 @@ func TestReconcileNvidiaInstanceModelsAddsUpdatesAndDeletes(t *testing.T) { maxTokens := 131072 maxDimension := 2048 remote := []modelModule.ListModelResponse{ - {Name: "nvidia/keep", MaxTokens: &maxTokens, ModelTypes: []string{"chat", "vision"}}, - {Name: "nvidia/new-embed", MaxTokens: ptrService(8192), MaxDimension: &maxDimension, Dimensions: []int{1024, 2048}, ModelTypes: []string{"embedding"}}, + {Name: "nvidia/keep", MaxOutput: &maxTokens, ModelTypes: []string{"chat", "vision"}}, + {Name: "nvidia/new-embed", MaxOutput: ptrService(8192), MaxDimension: &maxDimension, Dimensions: []int{1024, 2048}, ModelTypes: []string{"embedding"}}, } err := NewModelProviderService().reconcileNvidiaInstanceModels(context.Background(), db, provider, instance, remote) @@ -292,7 +292,7 @@ func TestReconcileNvidiaInstanceModelsAddsUpdatesAndDeletes(t *testing.T) { } var got []*entity.TenantModel - if err := db.Order("model_name").Find(&got).Error; err != nil { + if err = db.Order("model_name").Find(&got).Error; err != nil { t.Fatalf("list models: %v", err) } if len(got) != 2 || got[0].ModelName != "nvidia/keep" || got[1].ModelName != "nvidia/new-embed" {