feat: add Bailian image generation support
This commit is contained in:
@@ -8,6 +8,7 @@ import { accountManagementConfigured } from "@/lib/server/organization-client";
|
||||
import { rootDir } from "@/lib/server/runtime";
|
||||
import { shouldMockVisualApi } from "@/lib/volcengine/visual-client";
|
||||
import type { EnabledImageCapability } from "@/lib/types";
|
||||
import { getBailianConfig, shouldMockBailian } from "@/lib/bailian/client";
|
||||
|
||||
export type SettingsField = {
|
||||
key: string;
|
||||
@@ -133,6 +134,18 @@ const settingDefinitions: Array<{
|
||||
{ key: "SEEDANCE_API_KEY", label: "方舟 API Key", secret: true, type: "password" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "bailian",
|
||||
title: "阿里云百炼 API",
|
||||
description: "用于万相 2.7 文生图、参考图生图和图生视频。Base URL 会自动派生原生异步接口。",
|
||||
fields: [
|
||||
{ key: "BAILIAN_API_KEY", label: "百炼 API Key", secret: true, type: "password" },
|
||||
{ key: "BAILIAN_BASE_URL", label: "Base URL", defaultValue: "https://llm-126wneubbdo6dbr5.cn-beijing.maas.aliyuncs.com/compatible-mode/v1" },
|
||||
{ key: "BAILIAN_IMAGE_MODEL", label: "图片模型", defaultValue: "wan2.7-image-pro" },
|
||||
{ key: "BAILIAN_VIDEO_MODEL", label: "视频模型", defaultValue: "wan2.7-i2v-2026-04-25" },
|
||||
{ key: "BAILIAN_MOCK", label: "Mock 策略", type: "select", defaultValue: "auto", options: [{ label: "自动", value: "auto" }, { label: "总是 Mock", value: "true" }, { label: "总是真实接口", value: "false" }] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "oss",
|
||||
title: "OSS 资产存储",
|
||||
@@ -155,7 +168,18 @@ const engineFieldDefinitions: FieldDefinition[] = [
|
||||
defaultValue: "jimeng",
|
||||
options: [
|
||||
{ label: "即梦 / 火山视觉", value: "jimeng" },
|
||||
{ label: "EvoLink GPT Image 2", value: "evolink" }
|
||||
{ label: "EvoLink GPT Image 2", value: "evolink" },
|
||||
{ label: "阿里云百炼 Wan 2.7", value: "bailian" }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VIDEO_GENERATE_ENGINE",
|
||||
label: "视频生成",
|
||||
type: "select",
|
||||
defaultValue: "seedance",
|
||||
options: [
|
||||
{ label: "Seedance", value: "seedance" },
|
||||
{ label: "阿里云百炼 Wan 2.7", value: "bailian" }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -197,6 +221,7 @@ export async function getApiSettings() {
|
||||
visual: shouldMockVisualApi() ? "mock" : "real",
|
||||
evolink: shouldMockEvolinkApi() ? "mock" : "real",
|
||||
seedance: shouldMockSeedance() ? "mock" : "real",
|
||||
bailian: shouldMockBailian() ? "mock" : getBailianConfig().apiKey ? "real" : "missing",
|
||||
auth: authConfigSummary(auth),
|
||||
organization: accountManagementConfigured() ? "configured" : "missing",
|
||||
data: process.env.SUPABASE_SERVICE_ROLE_KEY ? "supabase" : "local"
|
||||
@@ -215,10 +240,10 @@ export async function getApiSettings() {
|
||||
}),
|
||||
{
|
||||
id: "video.generate",
|
||||
label: "Seedance 视频生成",
|
||||
reqKey: seedance.model,
|
||||
engine: "seedance",
|
||||
engineLabel: "Seedance",
|
||||
label: "视频生成",
|
||||
reqKey: engineAssignments.find((item) => item.id === "video.generate")?.reqKey || seedance.model,
|
||||
engine: engineAssignments.find((item) => item.id === "video.generate")?.engine || "seedance",
|
||||
engineLabel: engineAssignments.find((item) => item.id === "video.generate")?.engineLabel || "Seedance",
|
||||
enabled: true
|
||||
}
|
||||
],
|
||||
@@ -252,15 +277,16 @@ function buildEngineAssignments(fileEnv: Map<string, string>): EngineAssignment[
|
||||
const capabilities = getJimengCapabilities();
|
||||
const evolink = getEvolinkImageSettings();
|
||||
const seedance = getSeedanceConfig();
|
||||
const bailian = getBailianConfig();
|
||||
const generateEngine = currentEngineValue(engineFieldDefinitions[0], fileEnv);
|
||||
const inpaintEngine = currentEngineValue(engineFieldDefinitions[1], fileEnv);
|
||||
const inpaintEngine = currentEngineValue(engineFieldDefinitions[2], fileEnv);
|
||||
|
||||
return [
|
||||
imageEngineAssignment({
|
||||
capability: "image.generate",
|
||||
label: "图片生成",
|
||||
engine: generateEngine,
|
||||
reqKey: generateEngine === "evolink" ? evolink.model : capabilities["image.generate"].reqKey,
|
||||
reqKey: generateEngine === "bailian" ? bailian.imageModel : generateEngine === "evolink" ? evolink.model : capabilities["image.generate"].reqKey,
|
||||
field: engineFieldDefinitions[0],
|
||||
fileEnv
|
||||
}),
|
||||
@@ -269,7 +295,7 @@ function buildEngineAssignments(fileEnv: Map<string, string>): EngineAssignment[
|
||||
label: "局部重绘",
|
||||
engine: inpaintEngine,
|
||||
reqKey: inpaintEngine === "evolink" ? evolink.model : capabilities["image.inpaint"].reqKey,
|
||||
field: engineFieldDefinitions[1],
|
||||
field: engineFieldDefinitions[2],
|
||||
fileEnv
|
||||
}),
|
||||
{
|
||||
@@ -285,12 +311,13 @@ function buildEngineAssignments(fileEnv: Map<string, string>): EngineAssignment[
|
||||
{
|
||||
id: "video.generate",
|
||||
label: "视频生成",
|
||||
engine: "seedance",
|
||||
engineLabel: "Seedance",
|
||||
mode: shouldMockSeedance() ? "mock" : "seedance",
|
||||
modeLabel: shouldMockSeedance() ? "Mock" : "Seedance 真实接口",
|
||||
reqKey: seedance.model,
|
||||
configurable: false
|
||||
engine: currentVideoEngineValue(engineFieldDefinitions[1], fileEnv),
|
||||
engineLabel: currentVideoEngineValue(engineFieldDefinitions[1], fileEnv) === "bailian" ? "阿里云百炼" : "Seedance",
|
||||
mode: currentVideoEngineValue(engineFieldDefinitions[1], fileEnv) === "bailian" ? (shouldMockBailian() ? "mock" : "bailian") : (shouldMockSeedance() ? "mock" : "seedance"),
|
||||
modeLabel: currentVideoEngineValue(engineFieldDefinitions[1], fileEnv) === "bailian" ? (shouldMockBailian() ? "Mock" : "百炼真实接口") : (shouldMockSeedance() ? "Mock" : "Seedance 真实接口"),
|
||||
reqKey: currentVideoEngineValue(engineFieldDefinitions[1], fileEnv) === "bailian" ? bailian.videoModel : seedance.model,
|
||||
configurable: true,
|
||||
field: fieldWithValue(engineFieldDefinitions[1], currentVideoEngineValue(engineFieldDefinitions[1], fileEnv), isConfigured(engineFieldDefinitions[1].key, fileEnv))
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -336,21 +363,27 @@ function isConfigured(key: string, fileEnv: Map<string, string>) {
|
||||
}
|
||||
|
||||
function normalizeImageEngine(value: string | undefined): ImageCreationEngine {
|
||||
return value?.trim().toLowerCase() === "evolink" ? "evolink" : "jimeng";
|
||||
const normalized = value?.trim().toLowerCase();
|
||||
return normalized === "evolink" || normalized === "bailian" ? normalized : "jimeng";
|
||||
}
|
||||
|
||||
function imageEngineLabel(engine: ImageCreationEngine) {
|
||||
return engine === "evolink" ? "EvoLink" : "即梦";
|
||||
return engine === "evolink" ? "EvoLink" : engine === "bailian" ? "阿里云百炼" : "即梦";
|
||||
}
|
||||
|
||||
function modeForImageEngine(engine: ImageCreationEngine) {
|
||||
if (engine === "evolink") return shouldMockEvolinkApi() ? "mock" : "evolink";
|
||||
if (engine === "bailian") return shouldMockBailian() ? "mock" : "bailian";
|
||||
return shouldMockVisualApi() ? "mock" : "volcengine";
|
||||
}
|
||||
|
||||
function modeLabel(mode: string, engine: ImageCreationEngine) {
|
||||
if (mode === "mock") return "Mock";
|
||||
return engine === "evolink" ? "EvoLink 真实接口" : "即梦真实接口";
|
||||
return engine === "evolink" ? "EvoLink 真实接口" : engine === "bailian" ? "百炼真实接口" : "即梦真实接口";
|
||||
}
|
||||
|
||||
function currentVideoEngineValue(field: FieldDefinition, fileEnv: Map<string, string>) {
|
||||
return (process.env[field.key] ?? fileEnv.get(field.key) ?? field.defaultValue) === "bailian" ? "bailian" : "seedance";
|
||||
}
|
||||
|
||||
function envFilePath() {
|
||||
|
||||
Reference in New Issue
Block a user