From 2f667cede8ffcd5425ae1656363a6d698f4b134e Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 1 Feb 2026 16:28:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20LLM=20=E9=A9=B1=E5=8A=A8=E7=9A=84?= =?UTF-8?q?=E7=B2=BE=E5=87=86=E6=8F=90=E7=A4=BA=E8=AF=8D=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 使用 Qwen VL 根据历史对话动态优化提示词 2. 强调精准局部编辑,只修改用户指定的部分 3. 保护其他元素不被误改 4. 包含具体的编辑要求和避免项 Co-authored-by: Cursor --- app/(chat)/api/chat/route.ts | 9 +- lib/ai/prompt-optimizer.ts | 187 +++++++++++++++++++++++++++++++++-- 2 files changed, 184 insertions(+), 12 deletions(-) diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 5f5f3d1..fa0f4c1 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -467,16 +467,17 @@ export async function POST(request: Request) { console.log("[Smart Auto Mode] 💬 Conversational reply:", smartAutoFriendlyMessage); } - // 3. 如果是图片编辑类意图,优化提示词 + // 3. 如果是图片编辑类意图,使用 LLM 深度优化提示词 if (analysisResult.intent === "image_edit" && analysisResult.subIntent) { - const { optimizePrompt } = await import("@/lib/ai/prompt-optimizer"); - const optimizedResult = optimizePrompt({ + const { optimizePromptWithLLM } = await import("@/lib/ai/prompt-optimizer"); + const optimizedResult = await optimizePromptWithLLM({ originalPrompt: textContent, intent: analysisResult.intent, subIntent: analysisResult.subIntent, + historyMessages, // 🆕 传入历史对话上下文 }); - console.log("[Smart Auto Mode] ✨ Prompt optimized:", { + console.log("[Smart Auto Mode] ✨ Prompt optimized (LLM):", { original: textContent.substring(0, 50), optimized: optimizedResult.optimizedPrompt.substring(0, 100), }); diff --git a/lib/ai/prompt-optimizer.ts b/lib/ai/prompt-optimizer.ts index 55ca4d2..7c7ede7 100644 --- a/lib/ai/prompt-optimizer.ts +++ b/lib/ai/prompt-optimizer.ts @@ -146,19 +146,177 @@ const EDIT_TEMPLATES: Record< color_adjust: { template: - "颜色调整:对图片进行{adjustment}处理。要求:保持自然效果,色彩协调,不过度调整。", - negative: "色彩失真,过度调整,不自然,偏色严重", + "颜色调整:{original_request}。要求:精准修改指定部分的颜色,保持其他区域不变,色彩过渡自然协调。", + negative: "色彩失真,过度调整,不自然,偏色严重,其他区域被误改", extractors: { - adjustment: /(?:调整|增加|减少|提高|降低)(.+?)(?:,|。|$| )/, + // 匹配各种颜色修改表达方式 + target_color: /(?:改成|换成|变成|改为|换为|变为|调成|调整为)(.+?)(?:色|$)/, + target_object: /(?:把|将)?(.+?)(?:的)?(?:颜色|色)/, }, defaults: { - adjustment: "色彩优化", + original_request: "进行色彩优化处理", }, + // 特殊标记:使用原始请求 + useOriginalPrompt: true, }, }; +import { generateText } from "ai"; + +// 历史消息类型 +interface HistoryMessage { + role: "user" | "assistant"; + content: string; +} + +// LLM 优化提示词的系统提示 - 专注于精准局部编辑 +const LLM_OPTIMIZER_SYSTEM_PROMPT = `你是一个专业的AI图片编辑提示词优化专家。本系统主要用于产品图片编辑,需要精准控制编辑范围。 + +## 核心原则:精准局部编辑 +1. **只修改用户指定的部分**:明确指出要修改的对象/区域 +2. **保护其他元素**:强调保持其他所有元素完全不变 +3. **细节要求**:包含颜色、材质、光影、位置等具体参数 +4. **自然过渡**:修改区域与周围环境自然融合 + +## 输出格式(严格JSON) +{ + "optimizedPrompt": "精准的图片编辑指令", + "negativePrompt": "需要避免的效果" +} + +## 示例 + +用户请求:"把椅子颜色改成绿色" +{ + "optimizedPrompt": "【精准编辑】将图片中椅子的颜色改为绿色。具体要求:1.只修改椅子颜色,保持椅子的形状、材质纹理、光影反射完全不变;2.背景、地面、其他物品保持原样不做任何改动;3.绿色需自然协调,与原有光照环境匹配", + "negativePrompt": "背景改变,其他物品变色,形状变形,材质改变,光影不自然,整体色调偏移" +} + +用户请求:"把背景换成白色" +{ + "optimizedPrompt": "【精准编辑】将图片背景替换为纯白色(#FFFFFF)。具体要求:1.只替换背景区域,主体产品保持完全不变;2.主体边缘精准抠取,无残留背景色;3.保留主体自然投影效果", + "negativePrompt": "主体被裁切,边缘锯齿,主体颜色改变,产品变形,细节丢失" +} + +用户请求:"把产品放大一点" +{ + "optimizedPrompt": "【精准编辑】将图片中的产品主体等比例放大约20%。具体要求:1.保持产品清晰度和细节不丢失;2.保持产品比例不变形;3.背景自然填充延伸", + "negativePrompt": "产品模糊,比例变形,画质下降,背景突兀" +} + +用户历史说"抠图",现在说"再清晰一点" +{ + "optimizedPrompt": "【精准编辑】提升图片清晰度。具体要求:1.增强主体产品的锐度和细节;2.保持透明背景不变;3.不改变产品颜色和形状", + "negativePrompt": "过度锐化,噪点增加,颜色失真,边缘光晕" +} + +## 关键要求 +- 必须使用【精准编辑】开头,明确这是局部编辑任务 +- 必须列出"具体要求"说明要改什么、不改什么 +- negativePrompt 必须包含"其他元素改变"相关描述 +- 结合对话历史理解用户的连续编辑意图`; + /** - * 优化提示词 + * 🆕 使用 LLM 深度优化提示词(基于历史对话上下文) + */ +export async function optimizePromptWithLLM(params: { + originalPrompt: string; + intent: string; + subIntent?: string; + historyMessages?: HistoryMessage[]; +}): Promise { + const { originalPrompt, intent, subIntent, historyMessages } = params; + + console.log("[Prompt Optimizer LLM] Input:", { + originalPrompt, + intent, + subIntent, + historyCount: historyMessages?.length || 0 + }); + + // 只对图片编辑类意图进行 LLM 优化 + if (intent !== "image_edit") { + return { + originalPrompt, + optimizedPrompt: originalPrompt, + negativePrompt: "模糊,低质量,变形,水印,失真", + }; + } + + try { + // 动态导入避免循环依赖 + const { getEnabledAiModelsWithProvider } = await import("@/lib/db/queries"); + const { getLanguageModelById } = await import("./dynamic-provider"); + + // 获取千问3 VL 模型 + const allModels = await getEnabledAiModelsWithProvider(); + const qwenModel = allModels.find( + (m) => m.provider.type === "alibaba" && m.model.supportsVision + ); + + if (!qwenModel) { + console.log("[Prompt Optimizer LLM] No Qwen3 VL model, falling back to template"); + return optimizePrompt({ originalPrompt, intent, subIntent }); + } + + const model = await getLanguageModelById(qwenModel.model.id); + if (!model) { + console.log("[Prompt Optimizer LLM] Failed to get model, falling back to template"); + return optimizePrompt({ originalPrompt, intent, subIntent }); + } + + // 构建包含历史上下文的消息 + let contextMessage = ""; + if (historyMessages && historyMessages.length > 0) { + const recentHistory = historyMessages.slice(-6); // 最近3轮对话 + const historyText = recentHistory.map(msg => + `${msg.role === 'user' ? '用户' : 'AI'}: ${msg.content.substring(0, 150)}` + ).join('\n'); + contextMessage = `## 对话历史:\n${historyText}\n\n`; + } + + const userMessage = `${contextMessage}## 当前用户请求:\n"${originalPrompt}"\n\n## 识别的意图:${subIntent || '图片编辑'}\n\n请生成优化后的提示词:`; + + console.log("[Prompt Optimizer LLM] Calling Qwen3 VL for prompt optimization"); + + const { text: responseText } = await generateText({ + model, + system: LLM_OPTIMIZER_SYSTEM_PROMPT, + prompt: userMessage, + temperature: 0.2, + maxTokens: 200, + } as any); + + // 解析 JSON 响应 + const jsonMatch = responseText.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const result = JSON.parse(jsonMatch[0]); + console.log("[Prompt Optimizer LLM] Result:", result); + return { + originalPrompt, + optimizedPrompt: result.optimizedPrompt || originalPrompt, + negativePrompt: result.negativePrompt || "模糊,低质量,变形,失真", + friendlyMessage: FRIENDLY_MESSAGES[subIntent || ""]?.template, + }; + } catch (e) { + console.error("[Prompt Optimizer LLM] Failed to parse response:", e); + } + } + + // 解析失败,回退到模板优化 + console.log("[Prompt Optimizer LLM] Parse failed, falling back to template"); + return optimizePrompt({ originalPrompt, intent, subIntent }); + + } catch (error) { + console.error("[Prompt Optimizer LLM] Error:", error); + // 出错时回退到模板优化 + return optimizePrompt({ originalPrompt, intent, subIntent }); + } +} + +/** + * 优化提示词(模板方式 - 作为回退) */ export function optimizePrompt(params: { originalPrompt: string; @@ -187,7 +345,7 @@ export function optimizePrompt(params: { }; } - const template = EDIT_TEMPLATES[subIntent]; + const template = EDIT_TEMPLATES[subIntent] as any; if (!template) { console.log("[Prompt Optimizer] No template for subIntent:", subIntent); return { @@ -197,12 +355,25 @@ export function optimizePrompt(params: { }; } + // 🆕 对于某些子意图,直接使用原始提示词(因为用户的描述更精准) + // 例如:color_adjust - "把椅子颜色改成绿色" 比模板更精准 + if (template.useOriginalPrompt) { + console.log("[Prompt Optimizer] Using original prompt for", subIntent); + const optimizedPrompt = `${originalPrompt}。要求:精准执行用户要求,保持其他区域不变,效果自然协调。`; + return { + originalPrompt, + optimizedPrompt, + negativePrompt: template.negative, + friendlyMessage: FRIENDLY_MESSAGES[subIntent]?.template, + }; + } + // 使用模板生成优化后的提示词 let optimizedPrompt = template.template; // 从用户输入中提取参数并填充模板 for (const [key, regex] of Object.entries(template.extractors)) { - const match = originalPrompt.match(regex); + const match = originalPrompt.match(regex as RegExp); let value = match ? match[1].trim() : template.defaults[key] || ""; // 清理提取的值 @@ -217,7 +388,7 @@ export function optimizePrompt(params: { // 填充剩余的默认值 for (const [key, defaultValue] of Object.entries(template.defaults)) { - optimizedPrompt = optimizedPrompt.replace(`{${key}}`, defaultValue); + optimizedPrompt = optimizedPrompt.replace(`{${key}}`, defaultValue as string); } // 附加用户原始意图(如果优化后的提示词没有完全覆盖用户需求)