自动模式补发历史图片
This commit is contained in:
parent
ffd2d1a291
commit
84e22bcccb
@ -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); // 调试日志
|
||||
|
||||
// 🆕 检测是否是视频模型
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user