feat: 自动使用历史图片进行连续对话编辑
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

- 用户没有发送新图片时,自动使用历史中最近的图片
- 支持连续对话场景:换颜色、调整、重做等
- 优先使用AI生成的图片,其次是用户上传的图片
- 让对话更自然,不需要每次都重新上传图片

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name 2026-01-31 23:37:23 +08:00
parent 760509100c
commit 691e9862e7
2 changed files with 124 additions and 5 deletions

View File

@ -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");

View File

@ -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<AnalysisResult> {
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);