From 29f7a5c0e510fdb8d311918092d298403f72476c Mon Sep 17 00:00:00 2001 From: Dade Date: Wed, 2 Sep 2026 20:20:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E6=A8=A1=E5=9E=8B=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20-=20=E8=A7=86=E9=A2=91=E6=B5=8B=E8=AF=95=E6=8C=89?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=E7=94=BB=E5=83=8F=E5=9B=9E=E5=A1=AB=E6=AF=94?= =?UTF-8?q?=E4=BE=8B=E4=B8=8E=E5=88=86=E8=BE=A8=E7=8E=87=20(#401)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/service/channel_models.go | 43 +++++++++++++++++-- ...channel_models_admin_test_defaults_test.go | 36 ++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 backend/internal/service/channel_models_admin_test_defaults_test.go diff --git a/backend/internal/service/channel_models.go b/backend/internal/service/channel_models.go index 7d82b48ed..4cc651d4a 100644 --- a/backend/internal/service/channel_models.go +++ b/backend/internal/service/channel_models.go @@ -563,13 +563,25 @@ func (s *Service) TestAdminChannelModel(ctx context.Context, actor *model.User, } imageSize, imageQuality := "", "" var imageProfile *ImageCapabilityConfig - if capability == "image" { + videoRatio, videoResolution := videoTestDefaults(nil) + var videoProfile *VideoCapabilityConfig + switch capability { + case "image": profile, normalizeErr := NormalizeModelCapabilityConfigForModel(capability, string(protocol), providerModelKey, req.CapabilityConfig) if normalizeErr != nil { return nil, normalizeErr } imageProfile = profile.Image imageSize, imageQuality = imageTestDefaults(imageProfile) + case "video": + // 视频测试必须带上模型能力画像:声明式协议只按画像里的枚举回填分辨率名(如 480 -> 480p), + // 没有画像时会把裸数字发给上游,火山方舟等供应商会直接拒绝。 + profile, normalizeErr := NormalizeModelCapabilityConfigForModel(capability, string(protocol), providerModelKey, req.CapabilityConfig) + if normalizeErr != nil { + return nil, normalizeErr + } + videoProfile = profile.Video + videoRatio, videoResolution = videoTestDefaults(videoProfile) } input := canvasGenerationInput{ Mode: capability, @@ -585,11 +597,11 @@ func (s *Service) TestAdminChannelModel(ctx context.Context, actor *model.User, Headers: headers, Model: providerModelKey, ChannelModelKey: modelKey, - Size: map[string]string{"image": imageSize, "video": "16:9"}[capability], + Size: map[string]string{"image": imageSize, "video": videoRatio}[capability], Quality: imageQuality, Count: "1", VideoSeconds: videoSeconds, - VQuality: "720", + VQuality: videoResolution, VideoGenerateAudio: "false", VideoWatermark: "false", AudioVoice: "alloy", @@ -601,6 +613,9 @@ func (s *Service) TestAdminChannelModel(ctx context.Context, actor *model.User, if capability == "image" { input.ImageCapability = imageProfile } + if capability == "video" { + input.VideoCapability = videoProfile + } // 测试复用真实生成协议、运行时并发和熔断策略,但不创建用户任务或计费订单。 testCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) @@ -633,6 +648,28 @@ func (s *Service) TestAdminChannelModel(ctx context.Context, actor *model.User, } // 模型测试必须使用当前模型声明的默认参数,避免固定分辨率 SKU 被通用 1K 测试值误伤。 +// videoTestDefaults 从模型能力画像取测试用的比例和分辨率;画像缺失时回退到最通用的 16:9 / 720。 +func videoTestDefaults(profile *VideoCapabilityConfig) (string, string) { + if profile == nil { + return "16:9", "720" + } + ratio := strings.TrimSpace(profile.DefaultRatio) + if ratio == "" && len(profile.Ratios) > 0 { + ratio = strings.TrimSpace(profile.Ratios[0]) + } + if ratio == "" { + ratio = "16:9" + } + resolution := strings.TrimSpace(profile.DefaultResolution) + if resolution == "" && len(profile.Resolutions) > 0 { + resolution = strings.TrimSpace(profile.Resolutions[0]) + } + if resolution == "" { + resolution = "720" + } + return ratio, resolution +} + func imageTestDefaults(profile *ImageCapabilityConfig) (string, string) { if profile == nil { return "1024x1024", "auto" diff --git a/backend/internal/service/channel_models_admin_test_defaults_test.go b/backend/internal/service/channel_models_admin_test_defaults_test.go new file mode 100644 index 000000000..ff35cf098 --- /dev/null +++ b/backend/internal/service/channel_models_admin_test_defaults_test.go @@ -0,0 +1,36 @@ +package service + +import "testing" + +func TestVideoTestDefaultsFollowCapabilityProfile(t *testing.T) { + tests := []struct { + name string + profile *VideoCapabilityConfig + wantRatio string + wantResolution string + }{ + {name: "nil profile falls back", profile: nil, wantRatio: "16:9", wantResolution: "720"}, + {name: "declared defaults win", profile: &VideoCapabilityConfig{Ratios: []string{"9:16", "16:9"}, DefaultRatio: "16:9", Resolutions: []string{"480p", "720p"}, DefaultResolution: "720p"}, wantRatio: "16:9", wantResolution: "720p"}, + {name: "first enum when no default", profile: &VideoCapabilityConfig{Ratios: []string{"1:1"}, Resolutions: []string{"768p横"}}, wantRatio: "1:1", wantResolution: "768p横"}, + {name: "empty profile falls back", profile: &VideoCapabilityConfig{}, wantRatio: "16:9", wantResolution: "720"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ratio, resolution := videoTestDefaults(tt.profile) + if ratio != tt.wantRatio || resolution != tt.wantResolution { + t.Fatalf("videoTestDefaults() = (%q, %q), want (%q, %q)", ratio, resolution, tt.wantRatio, tt.wantResolution) + } + }) + } +} + +func TestVideoTestDefaultsResolveArkSeedanceEnum(t *testing.T) { + profile := DefaultModelCapabilityConfigForModel("volcengine-ark-video", "doubao-seedance-2-0-mini-260615").Video + _, resolution := videoTestDefaults(profile) + if resolution == "" || resolution == "720" { + t.Fatalf("Ark Seedance test resolution must come from the declared enum, got %q", resolution) + } + if got := videoResolutionNameRequest(profile, resolution); got != resolution { + t.Fatalf("declared resolution %q must round-trip through the profile, got %q", resolution, got) + } +}