diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index aa0ed56ab..f4b00a7f1 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -334,6 +334,7 @@ export async function POST(request: Request) { // 🆕 存储智能模式的相关信息 let smartAutoFriendlyMessage: string | undefined; // AI的自然对话回复 let smartAutoOptimizedPrompt: string | undefined; // 优化后的提示词(不修改用户消息,只用于API调用) + let smartAutoHistoryImage: string | undefined; // 从历史对话中提取的图片URL // ========== Smart Auto Mode Logic ========== if (finalModelId === "auto") { @@ -348,16 +349,68 @@ export async function POST(request: Request) { .join(" "); // @ts-ignore - 检查各种可能的图片类型 - const hasImage = lastUserMessage.parts.some( + let hasImage = lastUserMessage.parts.some( (p: any) => p.type === "file" || p.type === "image" || p.type === "image_url" ); // @ts-ignore - 提取图片URL - const imageUrls = lastUserMessage.parts + let imageUrls = lastUserMessage.parts .filter((p: any) => p.type === "file" && p.url) .map((p: any) => p.url as string); - console.log("[Smart Auto Mode] Input:", { textContent: textContent.substring(0, 100), hasImage, imageCount: imageUrls.length }); + // 🆕 历史图片上下文感知:如果用户没有发送新图片,自动使用历史中最近的图片 + // 逻辑:只要用户在对话中没有附上新图片,就默认继续处理之前的图片 + 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生成的) + 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; + } + } + } + } + + // 查找用户上传的图片 + 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; + } + } + } + + if (smartAutoHistoryImage) break; + } + + // 如果找到了历史图片,标记为有图片 + if (smartAutoHistoryImage) { + hasImage = true; + imageUrls = [smartAutoHistoryImage]; + console.log("[Smart Auto Mode] ✅ Auto-using history image for context continuity"); + } else { + console.log("[Smart Auto Mode] ℹ️ No image found in history, proceeding as pure text"); + } + } + + console.log("[Smart Auto Mode] Input:", { textContent: textContent.substring(0, 100), hasImage, imageCount: imageUrls.length, fromHistory: !!smartAutoHistoryImage }); // 2. 调用智能分析器 const { analyzeIntent } = await import("@/lib/ai/smart-analyzer"); @@ -365,6 +418,7 @@ export async function POST(request: Request) { text: textContent, hasImage, imageUrls, + imageFromHistory: !!smartAutoHistoryImage, // 🆕 标识图片是否来自历史 }); console.log("[Smart Auto Mode] Analysis result:", { @@ -943,6 +997,29 @@ export async function POST(request: Request) { })); } + // 🆕 如果使用了历史图片,将其注入到消息中 + if (smartAutoHistoryImage && messagesForAlibaba.length > 0) { + console.log("[Chat API] 🖼️ Injecting history image into message"); + messagesForAlibaba = messagesForAlibaba.map((msg) => { + // 检查消息中是否已有图片 + const hasExistingImage = msg.parts.some( + (p: any) => p.type === "file" || p.type === "image" + ); + + if (!hasExistingImage) { + // 注入历史图片 + return { + ...msg, + parts: [ + ...msg.parts, + { type: "file", url: smartAutoHistoryImage, mimeType: "image/png" }, + ], + }; + } + return msg; + }); + } + // 转换消息(阿里生图支持 URL,会自动上传 base64) const modelMessages = await convertMessagesWithImages(messagesForAlibaba, "alibaba-image"); diff --git a/lib/ai/smart-analyzer.ts b/lib/ai/smart-analyzer.ts index 1158decb0..bf2bcea0d 100644 --- a/lib/ai/smart-analyzer.ts +++ b/lib/ai/smart-analyzer.ts @@ -39,12 +39,25 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用 - inpaint: 去除某物、消除、擦掉、P掉、局部修改 - style_transfer: 风格化、卡通化、动漫风、改风格 - color_adjust: 调色、调整颜色、亮度、对比度 +- redo: 用户不满意之前的结果,想重新处理 ### vision - 图片理解(用户想让你看图说话) ### image_gen - 图片生成(用户想生成新图片) ### video_gen - 视频生成 ### chat - 普通对话 +## 特殊场景:连续对话(用户没有发送新图片,系统自动使用历史图片) + +当用户继续对话但没有发送新图片时,系统会自动找到之前的图片。这时候: +- 用户可能在继续描述想要的效果(如:"换成蓝色"、"再清晰一点"、"把背景去掉") +- 用户可能在修改之前的结果(如:"不满意"、"再调整"、"换个风格") +- 用户可能在追问(如:"还可以再亮一点吗"、"能不能换个颜色") + +处理方式: +- intent 通常是 image_edit +- subIntent 根据用户的具体要求判断 +- conversationalReply 要自然地回应用户,不需要特别强调"找到了之前的图片" + ## 输出格式(严格JSON) { "intent": "image_edit", @@ -86,6 +99,34 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用 "confidence": 0.5, "conversationalReply": "我看到你发了一张图片,你想对它做什么处理呢?比如抠图、换背景、变清晰?", "needsClarification": true +} + +连续对话场景 - 用户说"换成蓝色"(系统自动使用历史图片): +{ + "intent": "image_edit", + "subIntent": "color_adjust", + "confidence": 0.9, + "conversationalReply": "好的,我来帮你调整成蓝色~", + "needsClarification": false +} + +连续对话场景 - 用户说"不满意,再调整一下": +{ + "intent": "image_edit", + "subIntent": "redo", + "confidence": 0.8, + "conversationalReply": "没问题,你想怎么调整呢?比如换个颜色、调整风格?", + "needsClarification": true, + "clarifyingQuestions": ["你具体想调整哪方面呢?"] +} + +连续对话场景 - 用户说"再清晰一点": +{ + "intent": "image_edit", + "subIntent": "enhance", + "confidence": 0.9, + "conversationalReply": "好的,我再帮你提升一下清晰度~", + "needsClarification": false }`; /** @@ -95,10 +136,11 @@ export async function analyzeIntent(params: { text: string; hasImage: boolean; imageUrls?: string[]; + imageFromHistory?: boolean; // 🆕 图片是否来自历史记录 }): Promise { - const { text, hasImage, imageUrls } = params; + const { text, hasImage, imageUrls, imageFromHistory } = params; - console.log("[Smart Analyzer] Analyzing intent:", { text, hasImage, imageCount: imageUrls?.length }); + console.log("[Smart Analyzer] Analyzing intent:", { text, hasImage, imageCount: imageUrls?.length, imageFromHistory }); // 先尝试关键词快速匹配(高置信度场景直接返回,节省LLM调用) const quickResult = quickKeywordMatch(text, hasImage);