From 5361f7fc29aef49bbe0dd566e791b85bded48e4c Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 8 Feb 2026 23:16:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E7=94=9F=E5=9B=BE=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E6=97=B6=E8=B7=A8=E6=9C=8D=E5=8A=A1=E5=95=86=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=95=85=E9=9A=9C=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(chat)/api/chat/route.ts | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 27964ad..23f8a49 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -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 = { + "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;