From e4e81541a06ef03b9eef55f13330c36d81ee34ec Mon Sep 17 00:00:00 2001 From: Dade Date: Wed, 2 Sep 2026 20:19:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(protocol):=20=E7=81=AB=E5=B1=B1=E6=96=B9?= =?UTF-8?q?=E8=88=9F=20Seedream=20-=20=E6=AF=94=E4=BE=8B=E5=80=BC=E6=8D=A2?= =?UTF-8?q?=E7=AE=97=E4=B8=BA=E5=83=8F=E7=B4=A0=E5=B0=BA=E5=AF=B8=E5=86=8D?= =?UTF-8?q?=E5=8F=91=E7=BB=99=E4=B8=8A=E6=B8=B8=20(#400)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protocol/official_catalog_test.go | 34 ++++++++++++++++++ plugin-packages/generate-catalog.mjs | 9 ++++- .../volcengine-ark-seedream.yingce-plugin | Bin 6932 -> 7839 bytes 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/internal/protocol/official_catalog_test.go b/backend/internal/protocol/official_catalog_test.go index 8434b3c35..2927db4a9 100644 --- a/backend/internal/protocol/official_catalog_test.go +++ b/backend/internal/protocol/official_catalog_test.go @@ -431,3 +431,37 @@ func manifestTestBody(t *testing.T, spec RequestSpec) map[string]any { } return body } + +func TestOfficialArkSeedreamMapsAspectRatioToPixelSize(t *testing.T) { + adapter := officialPackageAdapter(t, "volcengine-ark-seedream.yingce-plugin", "volcengine-ark-image") + tests := []struct { + name, aspectRatio, wantSize string + }{ + {name: "ratio maps to 2K pixels", aspectRatio: "1:1", wantSize: "2048x2048"}, + {name: "landscape ratio", aspectRatio: "16:9", wantSize: "2560x1440"}, + {name: "auto maps to 2k tier", aspectRatio: "auto", wantSize: "2k"}, + {name: "pixel size passes through", aspectRatio: "1920x1080", wantSize: "1920x1080"}, + {name: "tier passes through", aspectRatio: "4k", wantSize: "4k"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + create, err := adapter.BuildCreate(context.Background(), RequestContext{Request: GenerationRequest{Model: "doubao-seedream-5-0-260128", Prompt: "circle", AspectRatio: tt.aspectRatio}}) + if err != nil { + t.Fatal(err) + } + if create.Path != "/api/v3/images/generations" { + t.Fatalf("Seedream create = %#v", create) + } + if body := manifestTestBody(t, create); body["size"] != tt.wantSize { + t.Fatalf("Seedream size = %#v, want %q", body["size"], tt.wantSize) + } + }) + } + create, err := adapter.BuildCreate(context.Background(), RequestContext{Request: GenerationRequest{Model: "doubao-seedream-5-0-260128", Prompt: "circle"}}) + if err != nil { + t.Fatal(err) + } + if _, ok := manifestTestBody(t, create)["size"]; ok { + t.Fatalf("Seedream must omit size when no ratio is requested") + } +} diff --git a/plugin-packages/generate-catalog.mjs b/plugin-packages/generate-catalog.mjs index 111a4176e..896f12aee 100644 --- a/plugin-packages/generate-catalog.mjs +++ b/plugin-packages/generate-catalog.mjs @@ -249,11 +249,18 @@ add({ response: { status: "succeeded", images: map(ref("response.data"), "item", { url: omit(ref("item.url")), dataUrl: conditional(ref("item.b64_json"), { $concat: ["data:image/png;base64,", ref("item.b64_json")] }) }), errorPaths: ["error.code"], messagePaths: ["error.message"] } }); +const arkSeedreamRatioSizes = [ + ["auto", "2k"], ["1:1", "2048x2048"], ["4:3", "2304x1728"], ["3:4", "1728x2304"], ["16:9", "2560x1440"], ["9:16", "1440x2560"], + ["3:2", "2496x1664"], ["2:3", "1664x2496"], ["21:9", "3024x1296"] +]; + add({ id: "volcengine-ark-seedream", providerId: "volcengine-ark-image", name: "Volcengine Ark Seedream Images", vendor: "Volcengine", capability: "image", baseUrl: "https://ark.cn-beijing.volces.com", auth: bearer, params: imageParams, create: jsonCreate("/api/v3/images/generations", { - model: ref("request.model"), prompt: ref("request.prompt"), size: omit(ref("request.aspectRatio")), + model: ref("request.model"), prompt: ref("request.prompt"), + // Ark 的 size 只接受 WIDTHxHEIGHT 或 2k/3k/4k;统一层的比例值在这里换算成 2K 档像素尺寸,像素或档位值原样透传。 + size: omit({ $switch: { cases: arkSeedreamRatioSizes.map(([ratio, size]) => ({ when: eq(ref("request.aspectRatio"), ratio), then: size })), default: ref("request.aspectRatio") } }), image: omit(map(ref("request.images"), "media", ref("media.value"))), sequential_image_generation: omit(ref("request.providerOptions.volcengine-ark-image.sequential_image_generation")), sequential_image_generation_options: omit(ref("request.providerOptions.volcengine-ark-image.sequential_image_generation_options")), diff --git a/plugin-packages/volcengine-ark-seedream.yingce-plugin b/plugin-packages/volcengine-ark-seedream.yingce-plugin index 7664c78566924a35e50c39d5c38fab5ba5eb2056..b2c2e197c1770f49032bd95513eb5b85dbf0abda 100644 GIT binary patch delta 7561 zcmZXZRZtw@vaN9@cyPC1gIi#5cL?t8?yiG-Ah^4`yAxc4yIYU}f_rZEez>RVoQJ>q z@9y>7Rcn38TzLYhN^-Dp*icYV0H^~k$_7+)Xz;(PZwH&e1ww&>vf+S&`uuNe=4k55 zV(s8&?qXqVYR+tLc0_2aN+fmD6)>FZLM8$;^~|hBubvI*a=m<`%PKybkSLHKoEq^l z_mtSRtL$%$g&yC<^RS~$4^$mO!&Hm>A_oYN=d4;PdkZ_y)rQD1kVdC;^6D{bm6CxM zwiXr^wm8TDdDMl*n0@raQNLIWv6!(i6Qc03W=4jp#6LIt*8Lu&-|{Lv3b=U|d=k!I zgBM6!h;gJZX`EdFS|Ov;m$VJ8E%aUTBY)4B;+1&TDKlY3erI>bQev5iVgrhrIhuW< z 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 Xzw$r$pBo|gIH`U#v}h`ze^>tj%GHYN