From 0901bc63290c154f74fb699847f1892d3c0a9e2c Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 31 Jan 2026 23:41:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E5=A4=9A=E5=BC=A0=E5=9B=BE=E7=89=87=E7=9A=84=E8=BF=9E=E7=BB=AD?= =?UTF-8?q?=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从历史对话中提取多张图片,支持多图融合编辑 - 收集同一条消息中的所有图片(用户上传或AI生成) - 将所有历史图片注入到后续编辑请求中 - 日志输出图片数量便于调试 Co-authored-by: Cursor --- app/(chat)/api/chat/route.ts | 78 ++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index f4b00a7..7742b8e 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -334,7 +334,7 @@ export async function POST(request: Request) { // 🆕 存储智能模式的相关信息 let smartAutoFriendlyMessage: string | undefined; // AI的自然对话回复 let smartAutoOptimizedPrompt: string | undefined; // 优化后的提示词(不修改用户消息,只用于API调用) - let smartAutoHistoryImage: string | undefined; // 从历史对话中提取的图片URL + let smartAutoHistoryImages: string[] = []; // 从历史对话中提取的图片URL(支持多张) // ========== Smart Auto Mode Logic ========== if (finalModelId === "auto") { @@ -358,53 +358,61 @@ export async function POST(request: Request) { .filter((p: any) => p.type === "file" && p.url) .map((p: any) => p.url as string); - // 🆕 历史图片上下文感知:如果用户没有发送新图片,自动使用历史中最近的图片 + // 🆕 历史图片上下文感知:如果用户没有发送新图片,自动使用历史中最近的图片(支持多张) // 逻辑:只要用户在对话中没有附上新图片,就默认继续处理之前的图片 if (!hasImage && messagesFromDb.length > 0) { console.log("[Smart Auto Mode] 🔍 No image in current message, auto-searching history..."); - // 从历史消息中倒序查找最近的图片 - // 优先找AI生成的图片(用户可能想修改生成结果),其次是用户上传的图片 + // 从历史消息中倒序查找最近一轮包含图片的消息 + // 收集该消息中的所有图片(支持多图融合编辑) for (let i = messagesFromDb.length - 1; i >= 0; i--) { const msg = messagesFromDb[i]; const parts = msg.parts as any[]; if (!parts) continue; - // 查找文本中的Markdown图片(AI生成的) + // 查找AI生成的图片(从Markdown中提取所有图片) if (msg.role === "assistant") { for (const part of parts) { if (part.type === "text" && part.text) { - // 匹配Markdown图片格式: ![alt](url) - const imgMatch = part.text.match(/!\[.*?\]\((https?:\/\/[^\s)]+)\)/); - if (imgMatch && imgMatch[1]) { - smartAutoHistoryImage = imgMatch[1]; - console.log("[Smart Auto Mode] 🖼️ Found AI-generated image:", smartAutoHistoryImage.substring(0, 80)); - break; + // 匹配所有Markdown图片格式: ![alt](url) + const imgMatches = part.text.matchAll(/!\[.*?\]\((https?:\/\/[^\s)]+)\)/g); + for (const match of imgMatches) { + if (match[1] && !smartAutoHistoryImages.includes(match[1])) { + smartAutoHistoryImages.push(match[1]); + } } } } - } - - // 查找用户上传的图片 - if (msg.role === "user" && !smartAutoHistoryImage) { - for (const part of parts) { - if ((part.type === "file" || part.type === "image") && part.url) { - smartAutoHistoryImage = part.url; - console.log("[Smart Auto Mode] 🖼️ Found user-uploaded image:", smartAutoHistoryImage.substring(0, 80)); - break; - } + // 如果在这条assistant消息中找到了图片,就停止搜索(使用最近一轮的结果) + if (smartAutoHistoryImages.length > 0) { + console.log("[Smart Auto Mode] 🖼️ Found AI-generated images:", smartAutoHistoryImages.length); + break; } } - if (smartAutoHistoryImage) break; + // 查找用户上传的图片(收集该消息中的所有图片) + if (msg.role === "user" && smartAutoHistoryImages.length === 0) { + for (const part of parts) { + if ((part.type === "file" || part.type === "image") && part.url) { + if (!smartAutoHistoryImages.includes(part.url)) { + smartAutoHistoryImages.push(part.url); + } + } + } + // 如果在这条user消息中找到了图片,就停止搜索 + if (smartAutoHistoryImages.length > 0) { + console.log("[Smart Auto Mode] 🖼️ Found user-uploaded images:", smartAutoHistoryImages.length); + break; + } + } } // 如果找到了历史图片,标记为有图片 - if (smartAutoHistoryImage) { + if (smartAutoHistoryImages.length > 0) { hasImage = true; - imageUrls = [smartAutoHistoryImage]; - console.log("[Smart Auto Mode] ✅ Auto-using history image for context continuity"); + imageUrls = smartAutoHistoryImages; + console.log("[Smart Auto Mode] ✅ Auto-using", smartAutoHistoryImages.length, "history image(s) for context continuity"); } else { console.log("[Smart Auto Mode] ℹ️ No image found in history, proceeding as pure text"); } @@ -418,7 +426,7 @@ export async function POST(request: Request) { text: textContent, hasImage, imageUrls, - imageFromHistory: !!smartAutoHistoryImage, // 🆕 标识图片是否来自历史 + imageFromHistory: smartAutoHistoryImages.length > 0, // 🆕 标识图片是否来自历史 }); console.log("[Smart Auto Mode] Analysis result:", { @@ -997,9 +1005,9 @@ export async function POST(request: Request) { })); } - // 🆕 如果使用了历史图片,将其注入到消息中 - if (smartAutoHistoryImage && messagesForAlibaba.length > 0) { - console.log("[Chat API] 🖼️ Injecting history image into message"); + // 🆕 如果使用了历史图片,将其注入到消息中(支持多张) + 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( @@ -1007,13 +1015,15 @@ export async function POST(request: Request) { ); if (!hasExistingImage) { - // 注入历史图片 + // 注入所有历史图片 + const imageParts = smartAutoHistoryImages.map((url) => ({ + type: "file" as const, + url, + mimeType: "image/png", + })); return { ...msg, - parts: [ - ...msg.parts, - { type: "file", url: smartAutoHistoryImage, mimeType: "image/png" }, - ], + parts: [...msg.parts, ...imageParts], }; } return msg;