自动模式补发历史图片

This commit is contained in:
Your Name 2026-02-05 22:04:31 +08:00
parent ffd2d1a291
commit 84e22bcccb

View File

@ -124,6 +124,54 @@ function applyHiddenPromptToMessages(messages: ChatMessage[], hiddenPrompt?: str
return cloned;
}
function guessImageMediaType(url: string): string {
const cleanUrl = url.split("?")[0]?.toLowerCase() || "";
if (cleanUrl.endsWith(".jpg") || cleanUrl.endsWith(".jpeg")) return "image/jpeg";
if (cleanUrl.endsWith(".webp")) return "image/webp";
if (cleanUrl.endsWith(".gif")) return "image/gif";
if (cleanUrl.endsWith(".bmp")) return "image/bmp";
if (cleanUrl.endsWith(".svg")) return "image/svg+xml";
return "image/png";
}
function injectHistoryImagesToLastUserMessage(
messages: ChatMessage[],
historyImages: string[]
): ChatMessage[] {
if (!historyImages || historyImages.length === 0) return messages;
let lastUserIndex = -1;
for (let i = messages.length - 1; i >= 0; i--) {
if (messages[i]?.role === "user") {
lastUserIndex = i;
break;
}
}
if (lastUserIndex < 0) return messages;
const lastUserMessage = messages[lastUserIndex];
const hasExistingImage = lastUserMessage.parts?.some(
(p: any) => p.type === "file" || p.type === "image" || p.type === "image_url"
);
if (hasExistingImage) return messages;
const imageParts = historyImages.map((url, index) => ({
type: "file" as const,
url,
name: `history-image-${index + 1}`,
mediaType: guessImageMediaType(url),
mimeType: guessImageMediaType(url),
}));
const updatedMessage: ChatMessage = {
...lastUserMessage,
parts: [...lastUserMessage.parts, ...imageParts],
};
return messages.map((msg, idx) => (idx === lastUserIndex ? updatedMessage : msg));
}
/**
* 自定义消息转换函数
* 注意:gemini-image 和 huanke-gemini 都需要 URL 格式(不是 Base64)
@ -823,7 +871,8 @@ export async function POST(request: Request) {
// 只传递最后一条用户消息,避免上下文历史干扰生图效果
const lastUserMessage = uiMessagesForModel.filter((m) => m.role === "user").pop();
const messagesForGemini = lastUserMessage ? [lastUserMessage] : uiMessagesForModel;
let messagesForGemini = lastUserMessage ? [lastUserMessage] : uiMessagesForModel;
messagesForGemini = injectHistoryImagesToLastUserMessage(messagesForGemini, smartAutoHistoryImages);
console.log("[Chat API] Gemini: Using only last user message (no history context)");
// 转换消息:gemini-image 需要 base64 格式,huanke-gemini 需要 URL 格式
@ -971,7 +1020,10 @@ export async function POST(request: Request) {
console.log("[Chat API] Executing Volcano Vision failover...");
// 转换消息(火山引擎会自动处理 Base64)
const volcanoMessages = await convertMessagesWithImages(uiMessagesForModel, "volcano");
const volcanoMessages = await convertMessagesWithImages(
injectHistoryImagesToLastUserMessage(uiMessagesForModel, smartAutoHistoryImages),
"volcano"
);
// 调用火山引擎生成(故障转移时只生成 1 张,保持与 Gemini 一致)
const volcanoResult = await (volcanoLanguageModel as any).doGenerate({
@ -1189,32 +1241,7 @@ export async function POST(request: Request) {
}));
}
// 🆕 如果使用了历史图片,将其注入到消息中(支持多张)
if (smartAutoHistoryImages.length > 0 && messagesForAlibaba.length > 0) {
console.log("[Chat API] 🖼️ Injecting", smartAutoHistoryImages.length, "history image(s) into message");
messagesForAlibaba = messagesForAlibaba.map((msg) => {
// 检查消息中是否已有图片
const hasExistingImage = msg.parts.some(
(p: any) => p.type === "file" || p.type === "image"
);
if (!hasExistingImage) {
// 注入所有历史图片
const imageParts = smartAutoHistoryImages.map((url) => ({
type: "file" as const,
url,
mediaType: "image/png",
mimeType: "image/png",
}));
return {
...msg,
// @ts-ignore - 类型兼容性问题,运行时正确
parts: [...msg.parts, ...imageParts],
};
}
return msg;
});
}
messagesForAlibaba = injectHistoryImagesToLastUserMessage(messagesForAlibaba, smartAutoHistoryImages);
const tryGenerateImage = async (modelIdToUse: string, isRetry: boolean) => {
// 转换消息(阿里生图支持 URL,会自动上传 base64)
@ -1435,6 +1462,8 @@ export async function POST(request: Request) {
return msg;
});
}
messagesForVolcano = injectHistoryImagesToLastUserMessage(messagesForVolcano, smartAutoHistoryImages);
const volcanoStream = createUIMessageStream({
execute: async ({ writer }) => {
@ -1763,7 +1792,10 @@ export async function POST(request: Request) {
console.log("[Chat API] Provider type:", (languageModel as any).provider); // 调试日志
// 转换消息,对于 Gemini 和千问视频将图片 URL 转换为 base64
const convertedMessages = await convertMessagesWithImages(uiMessagesForModel, (languageModel as any).provider || "");
const convertedMessages = await convertMessagesWithImages(
injectHistoryImagesToLastUserMessage(uiMessagesForModel, smartAutoHistoryImages),
(languageModel as any).provider || ""
);
console.log("[Chat API] Messages converted, count:", convertedMessages.length); // 调试日志
// 🆕 检测是否是视频模型