增强生图失败时跨服务商自动故障迁移
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-08 23:16:18 +08:00
parent 35d50973db
commit 5361f7fc29

View File

@ -1588,6 +1588,85 @@ export async function POST(request: Request) {
console.error(`[Chat API] ❌ Alibaba fallback model ${fallbackModelId} failed:`, fallbackError);
}
}
if (!fallbackSuccess) {
const providerPriority: Record<string, number> = {
"volcano-vision": 0,
gemini: 1,
"huanke-gemini": 2,
"alibaba-image": 3,
"ruxa-image": 4,
};
const crossProviderCandidates = allModels
.filter((m) => {
if (!m.model.supportsImageGen || !m.model.isEnabled || m.model.isSubModel) {
return false;
}
if (m.model.id === finalModelId) return false;
if (m.provider.id === alibabaModelConfig?.providerId) return false;
return true;
})
.sort((a, b) => {
const left = providerPriority[a.provider.type as string] ?? 99;
const right = providerPriority[b.provider.type as string] ?? 99;
if (left !== right) return left - right;
return (a.model.sortOrder ?? 0) - (b.model.sortOrder ?? 0);
});
for (const candidate of crossProviderCandidates) {
try {
console.log(
`[Chat API] 🔁 Cross-provider failover attempt: ${candidate.model.displayName} (${candidate.provider.type})`
);
const candidateLanguageModel = await getLanguageModelById(candidate.model.id);
if (!candidateLanguageModel || typeof (candidateLanguageModel as any).doGenerate !== "function") {
console.log(`[Chat API] Skip candidate without doGenerate: ${candidate.model.id}`);
continue;
}
const convertProvider =
candidate.provider.type === "ruxa-image"
? "ruxa-image"
: candidate.provider.type === "gemini"
? "gemini"
: candidate.provider.type === "huanke-gemini"
? "huanke-gemini"
: candidate.provider.type === "volcano-vision"
? "volcano"
: "alibaba-image";
const candidateMessages = await convertMessagesWithImages(
messagesForAlibaba,
convertProvider
);
const candidateResult = await (candidateLanguageModel as any).doGenerate({
messages: candidateMessages,
imageParams: requestBody.imageParams || { aspectRatio: "auto", imageSize: "2K", imageCount: 1 },
modelDisplayName: candidate.model.displayName,
overrideModelId: candidate.model.modelId,
});
if (candidateResult?.finishReason === "error") {
throw new Error(candidateResult.text || "图片生成失败");
}
imageMarkdown = candidateResult.text || "图片生成失败";
usedModelId = candidate.model.modelId;
fallbackSuccess = true;
console.log(
`[Chat API] ✅ Cross-provider failover succeeded: ${candidate.model.displayName} (${candidate.provider.type})`
);
break;
} catch (crossError) {
console.error(
`[Chat API] ❌ Cross-provider failover failed: ${candidate.model.displayName} (${candidate.provider.type})`,
crossError
);
}
}
}
if (!fallbackSuccess) {
throw primaryError;