feat: add Bailian image generation support
This commit is contained in:
@@ -28,6 +28,16 @@ import { importRemoteImageAsAsset, saveGeneratedAsset } from "@/lib/server/stora
|
||||
import { DEFAULT_OWNER_ID, toAbsoluteUrl } from "@/lib/server/runtime";
|
||||
import type { EnabledImageCapability, GenerationJob, VisualTaskQueryResponse } from "@/lib/types";
|
||||
import { queryVisualTask, shouldMockVisualApi, submitVisualTask } from "@/lib/volcengine/visual-client";
|
||||
import {
|
||||
bailianResultUrls,
|
||||
bailianStatus,
|
||||
bailianTaskId,
|
||||
buildBailianImagePayload,
|
||||
getBailianConfig,
|
||||
queryBailianTask,
|
||||
shouldMockBailian,
|
||||
submitBailianTask
|
||||
} from "@/lib/bailian/client";
|
||||
|
||||
export type SubmitImageJobInput = {
|
||||
ownerId?: string;
|
||||
@@ -59,18 +69,22 @@ export async function submitImageJob(input: SubmitImageJobInput, origin: string)
|
||||
const capability = getEnabledImageCapability(input.capability);
|
||||
const normalizedUrls = (input.imageUrls || []).map((url) => toAbsoluteUrl(url, origin));
|
||||
const engine = getEffectiveImageEngine(input.capability, input.engine);
|
||||
const providerPayload = engine === "evolink"
|
||||
? buildEvolinkImagePayload(input.capability, { ...input, imageUrls: normalizedUrls })
|
||||
: buildJimengPayload(input.capability, capability.reqKey, { ...input, imageUrls: normalizedUrls });
|
||||
const mock = engine === "evolink" ? shouldMockEvolinkApi() : shouldMockVisualApi();
|
||||
const reqKey = engine === "evolink" ? getEvolinkImageSettings().model : capability.reqKey;
|
||||
const providerPayload = engine === "bailian"
|
||||
? buildBailianImagePayload(input.capability, { ...input, imageUrls: normalizedUrls })
|
||||
: engine === "evolink"
|
||||
? buildEvolinkImagePayload(input.capability, { ...input, imageUrls: normalizedUrls })
|
||||
: buildJimengPayload(input.capability, capability.reqKey, { ...input, imageUrls: normalizedUrls });
|
||||
const bailianConfig = getBailianConfig();
|
||||
const mock = engine === "bailian" ? shouldMockBailian() : engine === "evolink" ? shouldMockEvolinkApi() : shouldMockVisualApi();
|
||||
const missingBailianKey = engine === "bailian" && !mock && !bailianConfig.apiKey;
|
||||
const reqKey = engine === "bailian" ? bailianConfig.imageModel : engine === "evolink" ? getEvolinkImageSettings().model : capability.reqKey;
|
||||
let job = await createGenerationJob({
|
||||
ownerId,
|
||||
externalClientId: input.externalClientId,
|
||||
capability: input.capability,
|
||||
provider: mock ? "mock" : engine === "evolink" ? "evolink" : "volcengine-visual",
|
||||
provider: mock ? "mock" : engine === "bailian" ? "bailian" : engine === "evolink" ? "evolink" : "volcengine-visual",
|
||||
reqKey,
|
||||
status: "queued",
|
||||
status: missingBailianKey ? "failed" : "queued",
|
||||
prompt: input.prompt,
|
||||
inputAssetIds: input.inputAssetIds || [],
|
||||
inputUrls: normalizedUrls,
|
||||
@@ -80,6 +94,7 @@ export async function submitImageJob(input: SubmitImageJobInput, origin: string)
|
||||
input,
|
||||
providerPayload
|
||||
},
|
||||
error: missingBailianKey ? { message: "缺少 BAILIAN_API_KEY,请先在设置页配置阿里云百炼 API Key。", retryable: true } : undefined,
|
||||
retryOf: input.retryOf,
|
||||
idempotencyKey: input.idempotencyKey,
|
||||
idempotencyFingerprint: input.idempotencyFingerprint,
|
||||
@@ -103,6 +118,12 @@ export async function advanceImageJob(jobId: string, origin: string): Promise<Ge
|
||||
async function dispatchImageJob(job: GenerationJob): Promise<GenerationJob> {
|
||||
const providerPayload = asRecord(job.requestPayload.providerPayload);
|
||||
try {
|
||||
if (job.provider === "bailian") {
|
||||
const response = await submitBailianTask("image", providerPayload);
|
||||
const taskId = bailianTaskId(response);
|
||||
if (!taskId) throw new Error(response.message || "百炼图片任务响应缺少 task_id。");
|
||||
return updateGenerationJob(job.id, { status: "queued", providerTaskId: taskId, responsePayload: response });
|
||||
}
|
||||
if (job.provider === "evolink") {
|
||||
const response = await submitEvolinkImageTask(providerPayload);
|
||||
const taskId = getEvolinkTaskId(response);
|
||||
@@ -164,6 +185,7 @@ export async function syncImageJob(jobId: string, origin: string): Promise<Gener
|
||||
if (job.provider === "evolink") {
|
||||
return syncEvolinkImageJob(job, origin);
|
||||
}
|
||||
if (job.provider === "bailian") return syncBailianImageJob(job, origin);
|
||||
|
||||
const queryPayload = buildJimengQueryPayload(job.reqKey, job.providerTaskId);
|
||||
let response: VisualTaskQueryResponse;
|
||||
@@ -238,6 +260,26 @@ export async function syncImageJob(jobId: string, origin: string): Promise<Gener
|
||||
});
|
||||
}
|
||||
|
||||
async function syncBailianImageJob(job: GenerationJob, origin: string): Promise<GenerationJob> {
|
||||
const response = await queryBailianTask(job.providerTaskId!);
|
||||
const status = bailianStatus(response);
|
||||
if (status !== "succeeded") {
|
||||
return updateGenerationJob(job.id, {
|
||||
status,
|
||||
responsePayload: response,
|
||||
error: status === "failed" ? { message: response.message || "百炼图片任务失败。", retryable: false } : undefined
|
||||
});
|
||||
}
|
||||
const urls = bailianResultUrls(response, "image");
|
||||
if (!urls.length) return updateGenerationJob(job.id, { status: "failed", responsePayload: response, error: { message: "百炼图片任务未返回结果地址。", retryable: true } });
|
||||
const assets = [];
|
||||
for (let index = 0; index < urls.length; index += 1) {
|
||||
assets.push(await importRemoteImageAsAsset({ ownerId: job.ownerId, url: urls[index], origin, source: sourceForCapability(job.capability), capability: job.capability, jobId: job.id, index, tags: assetTagsForJob(job) }));
|
||||
}
|
||||
await recordUsageEvent({ ownerId: job.ownerId, jobId: job.id, capability: job.capability, quantity: assets.length, estimatedUnit: "image" });
|
||||
return updateGenerationJob(job.id, { status: "succeeded", outputAssetIds: assets.map((asset) => asset.id), responsePayload: response });
|
||||
}
|
||||
|
||||
async function syncEvolinkImageJob(job: GenerationJob, origin: string): Promise<GenerationJob> {
|
||||
if (!job.providerTaskId) return job;
|
||||
let response: EvolinkTaskResponse;
|
||||
|
||||
Reference in New Issue
Block a user