增加2.5模型调用

This commit is contained in:
andy committed 2026-09-23 15:10:13 +08:00
1 parent 3f29ba716a
commit be655b6569
32 files changed
+1075 -56

No files matched your search

+45 -3
View File
@@ -194,6 +194,18 @@ func providerImageTargets(getenv postgres.Getenv) map[string]jobs.ProviderTarget
}
}
func providerImageModels(getenv postgres.Getenv) map[string]jobs.ProviderTarget {
models := []string{"gpt-image-2", "gpt-image-2.5-flare", "gpt-image-2.5-sunburst", firstNonEmpty(getenv("EVOLINK_IMAGE_MODEL"), "gpt-image-2")}
targets := make(map[string]jobs.ProviderTarget, len(models))
for _, model := range models {
targets[model] = jobs.ProviderTarget{
Provider: "evolink", Model: model,
Settings: map[string]any{"quality": firstNonEmpty(getenv("EVOLINK_IMAGE_QUALITY"), "medium")},
}
}
return targets
}
func providerVideoTargets(getenv postgres.Getenv) map[string]jobs.ProviderTarget {
seedanceModel := firstNonEmpty(getenv("SEEDANCE_MODEL"), "doubao-seedance-2-0-260128")
return map[string]jobs.ProviderTarget{
@@ -293,8 +305,13 @@ func capabilitySummary(getenv postgres.Getenv) func(context.Context) (any, error
primaryVideo["label"] = "百炼图生视频"
primaryVideo["limits"] = bailianVideoCapabilityLimits()
}
imageCapability := map[string]any{"id": "image.generate", "label": imageCapabilityLabel(engine), "kind": "image", "engine": engine, "provider": provider, "reqKey": imageModel(getenv)}
imageCapability["evolink"] = evolinkImageCapability(getenv)
if engine == "evolink" {
imageCapability["models"] = evolinkImageModelOptions(getenv)
}
return []any{
map[string]any{"id": "image.generate", "label": imageCapabilityLabel(engine), "kind": "image", "engine": engine, "provider": provider, "reqKey": imageModel(getenv)},
imageCapability,
primaryVideo,
map[string]any{"id": "video.generate.bailian", "label": "百炼图生视频", "kind": "video", "engine": "bailian", "provider": "bailian", "reqKey": firstNonEmpty(getenv("BAILIAN_VIDEO_MODEL"), "wan2.7-i2v-2026-04-25"), "limits": bailianVideoCapabilityLimits()},
map[string]any{"id": "video.generate.minimax", "label": "MiniMax H3 视频生成", "kind": "video", "engine": "minimax", "provider": "minimax", "reqKey": providers.MinimaxH3Model, "limits": minimaxVideoCapabilityLimits()},
@@ -302,6 +319,26 @@ func capabilitySummary(getenv postgres.Getenv) func(context.Context) (any, error
}
}
func evolinkImageModelOptions(getenv postgres.Getenv) []any {
options := []any{
map[string]any{"id": "gpt-image-2", "label": "GPT Image 2"},
map[string]any{"id": "gpt-image-2.5-flare", "label": "GPT Image 2.5 Flare"},
map[string]any{"id": "gpt-image-2.5-sunburst", "label": "GPT Image 2.5 Sunburst"},
}
custom := firstNonEmpty(getenv("EVOLINK_IMAGE_MODEL"), "gpt-image-2")
if custom != "gpt-image-2" && custom != "gpt-image-2.5-flare" && custom != "gpt-image-2.5-sunburst" {
options = append(options, map[string]any{"id": custom, "label": custom})
}
return options
}
func evolinkImageCapability(getenv postgres.Getenv) map[string]any {
return map[string]any{
"reqKey": firstNonEmpty(getenv("EVOLINK_IMAGE_MODEL"), "gpt-image-2"),
"models": evolinkImageModelOptions(getenv),
}
}
func seedanceCapabilityLimits(model string) map[string]any {
maximum := 15
if model == "doubao-seedance-2-5-260628" {
@@ -346,6 +383,11 @@ func runtimeHealthDetails(getenv postgres.Getenv) httpapi.HealthDetails {
}
}
videoCapability := map[string]any{"id": "video.generate", "label": "视频生成", "engine": video, "engineLabel": videoLabel, "reqKey": videoModel(getenv)}
imageCapability := map[string]any{"id": "image.generate", "label": imageCapabilityLabel(image), "engine": image, "engineLabel": imageLabel, "reqKey": imageModel(getenv)}
imageCapability["evolink"] = evolinkImageCapability(getenv)
if image == "evolink" {
imageCapability["models"] = evolinkImageModelOptions(getenv)
}
if video == "seedance" {
videoCapability["models"] = seedanceModelOptions()
}
@@ -357,7 +399,7 @@ func runtimeHealthDetails(getenv postgres.Getenv) httpapi.HealthDetails {
MinimaxMode: providerMode(strings.TrimSpace(getenv("MINIMAX_API_KEY")) != "", "minimax"),
AuthMode: authMode,
Capabilities: []any{
map[string]any{"id": "image.generate", "label": imageCapabilityLabel(image), "engine": image, "engineLabel": imageLabel, "reqKey": imageModel(getenv)},
imageCapability,
videoCapability,
},
}
@@ -477,7 +519,7 @@ func configuredProviderJobBuilder(getenv postgres.Getenv, enforceAvailability bo
return jobs.ProviderJobBuilder{
ImageProvider: imageProvider(getenv), VideoProvider: videoProvider(getenv),
ImageModel: imageModel(getenv), VideoModel: videoModel(getenv), ImageEngine: imageEngine(getenv), VideoEngine: videoEngine(getenv),
ImageEngines: providerImageTargets(getenv), VideoEngines: providerVideoTargets(getenv), VideoModels: providerVideoModels(getenv), UnavailableProviders: unavailable, NewID: applicationJobID,
ImageEngines: providerImageTargets(getenv), ImageModels: providerImageModels(getenv), VideoEngines: providerVideoTargets(getenv), VideoModels: providerVideoModels(getenv), UnavailableProviders: unavailable, NewID: applicationJobID,
}
}
@@ -190,6 +190,72 @@ func TestRuntimeProviderJobBuilderRefreshesDatabaseSettings(t *testing.T) {
}
}
func TestEvoLinkImageModelOptionsAndConfiguredDefault(t *testing.T) {
getenv := func(name string) string {
switch name {
case "IMAGE_GENERATE_ENGINE":
return "evolink"
case "EVOLINK_IMAGE_MODEL":
return "custom-image-model"
case "EVOLINK_IMAGE_QUALITY":
return "high"
default:
return ""
}
}
options := evolinkImageModelOptions(getenv)
if len(options) != 4 || options[3].(map[string]any)["id"] != "custom-image-model" {
t.Fatalf("options=%#v", options)
}
capabilities, err := capabilitySummary(getenv)(context.Background())
if err != nil {
t.Fatal(err)
}
image := capabilities.([]any)[0].(map[string]any)
if image["reqKey"] != "custom-image-model" || len(image["models"].([]any)) != 4 {
t.Fatalf("image capability=%#v", image)
}
builder := configuredProviderJobBuilder(getenv, false)
for _, model := range []string{"gpt-image-2", "gpt-image-2.5-flare", "gpt-image-2.5-sunburst", "custom-image-model"} {
command, err := builder.Build(context.Background(), "owner", "", "image.generate", "", map[string]any{
"engine": "evolink", "model": model, "prompt": "draw",
})
if err != nil {
t.Fatalf("model %s: %v", model, err)
}
var request providers.Request
if err := json.Unmarshal(command.Job.RequestPayload, &request); err != nil {
t.Fatal(err)
}
if command.Job.ReqKey != model || request.Model != model || request.Settings["quality"] != "high" {
t.Fatalf("model %s: job=%#v request=%#v", model, command.Job, request)
}
}
}
func TestImageCapabilityExposesEvoLinkDefaultWhenPrimaryIsJimeng(t *testing.T) {
getenv := func(name string) string {
if name == "EVOLINK_IMAGE_MODEL" {
return "gpt-image-2.5-sunburst"
}
return ""
}
capabilities, err := capabilitySummary(getenv)(context.Background())
if err != nil {
t.Fatal(err)
}
image := capabilities.([]any)[0].(map[string]any)
evolink := image["evolink"].(map[string]any)
if image["engine"] != "jimeng" || evolink["reqKey"] != "gpt-image-2.5-sunburst" || len(evolink["models"].([]any)) != 3 {
t.Fatalf("image capability=%#v", image)
}
health := runtimeHealthDetails(getenv)
healthImage := health.Capabilities[0].(map[string]any)
if healthImage["evolink"].(map[string]any)["reqKey"] != "gpt-image-2.5-sunburst" {
t.Fatalf("health capability=%#v", healthImage)
}
}
func TestRuntimeProviderJobBuilderRoutesSeedreamWithoutReplacingJimeng(t *testing.T) {
values := map[string]string{
"SEEDANCE_API_KEY": "ark-secret",