fix: recognize common multimodal text models

This commit is contained in:
Codex committed 2026-09-19 20:40:55 +08:00
1 parent 376770aad6
commit 43f30b9a84
4 files changed
+68 -5

No files matched your search

+19 -2
View File
@@ -207,9 +207,13 @@ func legacyImageSizeValues() []string {
}
func DefaultModelCapabilityConfigForModel(protocol string, modelName string) *ModelCapabilityConfig {
// 文本模型是否支持视觉输入不能从协议或模型名可靠推断,默认关闭,由管理员按真实上游能力开启。
streaming := true
text := &TextCapabilityConfig{Streaming: &streaming, References: TextReferenceConfig{PromptMaxChars: 32000}}
textReferences := TextReferenceConfig{PromptMaxChars: 32000}
if isKnownMultimodalTextModel(protocol, modelName) {
textReferences.MaxImages = 16
textReferences.MaxImageBytes = 30 * 1024 * 1024
}
text := &TextCapabilityConfig{Streaming: &streaming, References: textReferences}
video := &VideoCapabilityConfig{
References: VideoReferenceConfig{PromptMaxChars: DefaultVideoPromptMaxChars, MinImages: 0, MaxImages: 9, MaxImageBytes: 30 * 1024 * 1024, MaxVideos: 0, MaxVideoBytes: 0, MaxVideoDuration: 0, MaxAudios: 0, MaxAudioBytes: 0, MaxAudioDuration: 0},
Duration: VideoDurationConfig{Selection: "range", Min: 1, Max: 15, Step: 1, Default: 6},
@@ -275,6 +279,11 @@ func DefaultModelCapabilityConfigForModel(protocol string, modelName string) *Mo
return &ModelCapabilityConfig{Version: 1, Text: text, Image: DefaultImageCapabilityConfig(protocol, modelName), Video: video}
}
func isKnownMultimodalTextModel(protocol string, modelName string) bool {
model := strings.ToLower(strings.TrimSpace(modelName))
return strings.Contains(model, "gemini") || strings.Contains(model, "gpt") || strings.Contains(model, "doubao") || strings.Contains(model, "豆包") || strings.EqualFold(strings.TrimSpace(protocol), "gemini")
}
func DecodeModelCapabilityConfig(raw string) (*ModelCapabilityConfig, error) {
if strings.TrimSpace(raw) == "" {
return nil, nil
@@ -323,6 +332,14 @@ func NormalizeModelCapabilityConfigForModel(capability string, protocol string,
return nil, BadAuthRequest("请配置文本模型能力参数")
}
text := *input.Text
if isKnownMultimodalTextModel(protocol, modelName) && text.References.MaxImages == 0 {
// 旧配置是在文本模型默认不接收图片时生成的;Gemini 文本模型
// 通过兼容协议仍然会接收图片 parts,因此自动修复旧的 0 上限。
text.References.MaxImages = 16
if text.References.MaxImageBytes == 0 {
text.References.MaxImageBytes = 30 * 1024 * 1024
}
}
if text.Streaming == nil {
streaming := true
text.Streaming = &streaming
@@ -6,6 +6,23 @@ import (
"testing"
)
func TestDefaultModelCapabilityConfigRecognizesKnownTextVisionFamilies(t *testing.T) {
gemini := DefaultModelCapabilityConfigForModel("chat-completion", "gemini-3.8-flash-high")
gpt := DefaultModelCapabilityConfigForModel("chat-completion", "gpt-4o")
doubao := DefaultModelCapabilityConfigForModel("chat-completion", "doubao-seed-1.6-flash")
plain := DefaultModelCapabilityConfigForModel("chat-completion", "plain-text-model")
if gemini.Text == nil || gemini.Text.References.MaxImages != 16 || gemini.Text.References.MaxImageBytes != 30*1024*1024 {
t.Fatalf("Gemini text vision defaults = %#v", gemini.Text)
}
if gpt.Text == nil || gpt.Text.References.MaxImages != 16 || doubao.Text == nil || doubao.Text.References.MaxImages != 16 {
t.Fatalf("known multimodal text vision defaults: gpt=%#v doubao=%#v", gpt.Text, doubao.Text)
}
if plain.Text == nil || plain.Text.References.MaxImages != 0 {
t.Fatalf("plain text vision defaults = %#v", plain.Text)
}
}
func TestValidateImageTaskRejectsOversizedGrokPromptByUTF8Bytes(t *testing.T) {
prompt := strings.Repeat("中", 4001)
input := canvasGenerationInput{