57 lines
2.4 KiB
TypeScript
57 lines
2.4 KiB
TypeScript
export type CreativeAnalysisModel = {
|
|
id: string;
|
|
label: string;
|
|
modelId: string;
|
|
providerType: string;
|
|
supportsVision: boolean;
|
|
};
|
|
|
|
type CreativeAnalysisRequest = {
|
|
mode: "agent-plan" | "story-script" | "character-scene-extraction";
|
|
prompt: string;
|
|
nodeTitle: string;
|
|
models: CreativeAnalysisModel[];
|
|
preferredModelRef?: string;
|
|
imageUrls?: string[];
|
|
videoUrls?: string[];
|
|
};
|
|
|
|
function modelPriority(model: CreativeAnalysisModel) {
|
|
if (model.providerType === "alibaba" && model.modelId === "qwen3.8-max") return 0;
|
|
if (model.providerType === "alibaba" && model.modelId === "qwen3.8-omni-flash") return 1;
|
|
return 2;
|
|
}
|
|
|
|
export async function requestCreativeAnalysis(input: CreativeAnalysisRequest): Promise<Record<string, unknown>> {
|
|
const hasVisualInput = Boolean(input.imageUrls?.length || input.videoUrls?.length);
|
|
const compatible = input.models.filter(model => !hasVisualInput || model.supportsVision);
|
|
const selected = input.preferredModelRef
|
|
? compatible.find(model => model.id === input.preferredModelRef || model.modelId === input.preferredModelRef)
|
|
: undefined;
|
|
if (input.preferredModelRef && !selected) throw new Error("所选模型不支持当前素材,请重新选择模型");
|
|
const candidates = selected ? [selected] : [...compatible].sort((left, right) => modelPriority(left) - modelPriority(right));
|
|
const attempts: (CreativeAnalysisModel | undefined)[] = candidates.length ? candidates : [undefined];
|
|
let lastError = "分析失败,请稍后重试";
|
|
|
|
for (const [index, model] of attempts.entries()) {
|
|
const response = await fetch("/api/canvas/workflow/analyze", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({
|
|
mode: input.mode,
|
|
prompt: input.prompt,
|
|
nodeTitle: input.nodeTitle,
|
|
preferredModelRef: model?.id,
|
|
imageUrls: input.imageUrls?.slice(0, 4) || [],
|
|
videoUrls: input.videoUrls?.slice(0, 2) || [],
|
|
}),
|
|
});
|
|
const result = await response.json().catch(() => ({}));
|
|
if (response.ok && result.success) return result.data as Record<string, unknown>;
|
|
lastError = String(result.error || "分析失败,请稍后重试");
|
|
const authenticationFailure = /invalid authentication|invalid token|invalid api.?key|authentication failed|鉴权失败|认证失败/i.test(lastError);
|
|
if (selected || !authenticationFailure || index === attempts.length - 1) break;
|
|
}
|
|
throw new Error(lastError);
|
|
}
|