# 智能图片编辑 - 实施开发指南 > 版本: v1.0 > 日期: 2025-01-31 > 目标: 在聊天对话框中实现智能图片编辑功能 --- ## 一、核心流程 ``` 用户在对话框中发送 [图片 + 文字] │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ POST /api/chat │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 1. 提取用户消息 │ │ │ │ - 图片 URL (from message.parts where type='file') │ │ │ │ - 文字内容 (from message.parts where type='text') │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 2. 智能意图分析 (如果 modelId === 'auto') │ │ │ │ - 调用 Qwen3 VL 分析用户意图 │ │ │ │ - 返回: intent, subIntent, confidence │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 3. 提示词优化 (仅图片编辑类意图) │ │ │ │ - 根据子意图选择模板 │ │ │ │ - 填充用户参数,生成专业提示词 │ │ │ │ - 添加负面提示词 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 4. 模型路由 │ │ │ │ - 根据意图选择最佳模型 │ │ │ │ - 图片编辑 → alibaba-image │ │ │ │ - 视觉理解 → alibaba (Qwen3 VL) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 5. 调用对应模型生成 │ │ │ │ - 使用优化后的提示词 │ │ │ │ - 传入用户图片 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 6. 返回结果到对话框 │ │ │ │ - 编辑后的图片 (Markdown格式) │ │ │ │ - 保存到数据库 │ │ │ └─────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘ ``` --- ## 二、需要修改/创建的文件 ### 2.1 新建文件 | 文件路径 | 作用 | |---------|------| | `lib/ai/smart-analyzer.ts` | 智能意图分析器 | | `lib/ai/prompt-optimizer.ts` | 提示词优化器 | | `lib/ai/model-router.ts` | 智能模型路由器 | ### 2.2 修改文件 | 文件路径 | 修改内容 | |---------|---------| | `app/(chat)/api/chat/route.ts` | Auto Mode 逻辑替换 | --- ## 三、详细代码实现 ### 3.1 创建 `lib/ai/smart-analyzer.ts` ```typescript /** * 智能意图分析器 * 使用 Qwen3 VL 分析用户输入,识别图片编辑意图 */ import { generateText } from "ai"; import { getLanguageModelById } from "./dynamic-provider"; import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; // 分析结果类型 export interface AnalysisResult { intent: "image_edit" | "vision" | "image_gen" | "video_gen" | "chat"; subIntent?: string; confidence: number; optimizedPrompt?: string; negativePrompt?: string; suggestedModel?: string; needsClarification?: boolean; clarifyingQuestions?: string[]; } // 系统提示词 - 针对图片编辑场景优化 const ANALYZER_SYSTEM_PROMPT = `你是一个专业的图片编辑意图分析专家。请分析用户的请求,判断其意图类型。 ## 意图分类(按优先级) ### 1. image_edit - 图片编辑(最高优先级,需要用户上传了图片) 子意图: - remove_background: 抠图、去背景、透明背景、去除背景 - replace_background: 换背景、改背景、白底、场景替换、背景换成 - enhance: 变清晰、高清、锐化、降噪、提升质量、修复 - extend: 扩展、拓展、延伸、outpainting、扩图 - inpaint: 去除XX、消除、擦掉、修改XX部分、局部修改、P掉 - style_transfer: 风格化、卡通化、动漫风、油画风、改风格 - resize: 缩放、放大、缩小、调整尺寸、裁剪 - color_adjust: 调色、调整颜色、亮度、对比度、饱和度 ### 2. vision - 图片理解(需要用户上传了图片) 触发词:看、识别、分析、描述、这是什么、有什么 ### 3. image_gen - 图片生成(不需要上传图片) 触发词:画、绘制、生成图片、创建、设计 ### 4. video_gen - 视频生成 触发词:视频、动画、动起来 ### 5. chat - 普通对话(默认) ## 输出格式(严格JSON) { "intent": "image_edit", "subIntent": "replace_background", "confidence": 0.95, "optimizedPrompt": "优化后的提示词", "negativePrompt": "需要避免的内容", "needsClarification": false, "clarifyingQuestions": [] } ## 特殊规则 1. 如果用户上传了图片且有编辑类关键词 → image_edit 2. 如果用户上传了图片但意图不明确 → needsClarification: true,并提供澄清问题 3. 如果用户要求编辑但没上传图片 → needsClarification: true,提示"请上传图片"`; /** * 分析用户意图 */ export async function analyzeIntent(params: { text: string; hasImage: boolean; imageUrls?: string[]; }): Promise { const { text, hasImage, imageUrls } = params; // 获取千问3 VL 模型 const allModels = await getEnabledAiModelsWithProvider(); const qwenModel = allModels.find( (m) => m.provider.type === "alibaba" && m.model.supportsVision ); // 如果没有可用的分析模型,使用回退逻辑 if (!qwenModel) { console.log("[Smart Analyzer] No Qwen3 VL model found, using fallback"); return fallbackKeywordAnalysis(text, hasImage); } try { const model = await getLanguageModelById(qwenModel.model.id); if (!model) { return fallbackKeywordAnalysis(text, hasImage); } // 构建用户消息 const userMessage = hasImage ? `用户上传了图片,请求内容:"${text}"` : `用户请求(无图片):"${text}"`; console.log("[Smart Analyzer] Analyzing with Qwen3 VL:", userMessage); // 调用模型分析 const { text: responseText } = await generateText({ model, system: ANALYZER_SYSTEM_PROMPT, prompt: userMessage, temperature: 0.1, // 低温度保证稳定输出 maxTokens: 500, }); // 解析JSON响应 const jsonMatch = responseText.match(/\{[\s\S]*\}/); if (jsonMatch) { const result = JSON.parse(jsonMatch[0]) as AnalysisResult; console.log("[Smart Analyzer] Analysis result:", result); return result; } } catch (error) { console.error("[Smart Analyzer] Error:", error); } // 出错时使用回退逻辑 return fallbackKeywordAnalysis(text, hasImage); } /** * 回退方案:关键词匹配 */ function fallbackKeywordAnalysis( text: string, hasImage: boolean ): AnalysisResult { const lowerText = text.toLowerCase(); // 图片编辑关键词检测 if (hasImage) { // 抠图/去背景 if (/抠图|去背景|透明背景|去背|扣图/.test(lowerText)) { return { intent: "image_edit", subIntent: "remove_background", confidence: 0.9, }; } // 换背景 if (/换背景|白底|改背景|背景换成|纯色背景/.test(lowerText)) { return { intent: "image_edit", subIntent: "replace_background", confidence: 0.9, }; } // 图片增强 if (/变清晰|高清|锐化|降噪|提升质量|修复/.test(lowerText)) { return { intent: "image_edit", subIntent: "enhance", confidence: 0.9, }; } // 图像拓展 if (/扩展|拓展|延伸|扩图/.test(lowerText)) { return { intent: "image_edit", subIntent: "extend", confidence: 0.9, }; } // 局部修改 if (/去除|消除|擦掉|P掉|修改.*部分/.test(lowerText)) { return { intent: "image_edit", subIntent: "inpaint", confidence: 0.9, }; } // 风格迁移 if (/风格|卡通化|动漫风|油画风/.test(lowerText)) { return { intent: "image_edit", subIntent: "style_transfer", confidence: 0.9, }; } // 视觉理解 if (/看|识别|分析|描述|这是什么|有什么/.test(lowerText)) { return { intent: "vision", confidence: 0.8 }; } // 有图但意图不明确 return { intent: "image_edit", confidence: 0.5, needsClarification: true, clarifyingQuestions: [ "您想对这张图片做什么处理?(抠图/换背景/变清晰/其他)", ], }; } // 无图情况 if (/画|绘制|生成图|创建.*图/.test(lowerText)) { return { intent: "image_gen", confidence: 0.8 }; } if (/视频|动画|动起来/.test(lowerText)) { return { intent: "video_gen", confidence: 0.8 }; } // 默认对话 return { intent: "chat", confidence: 0.7 }; } export { fallbackKeywordAnalysis }; ``` ### 3.2 创建 `lib/ai/prompt-optimizer.ts` ```typescript /** * 提示词优化器 * 将用户简单输入转换为专业的图片编辑提示词 */ // 优化结果类型 export interface OptimizeResult { originalPrompt: string; optimizedPrompt: string; negativePrompt: string; } // 图片编辑子意图的提示词模板 const EDIT_TEMPLATES: Record< string, { template: string; negative: string; extractors: Record; } > = { remove_background: { template: "去除图片背景,保留主体完整,输出透明背景PNG格式,边缘处理平滑自然,保留细节(如发丝、毛发)", negative: "残留背景,毛边,边缘模糊,主体不完整,锯齿", extractors: {}, }, replace_background: { template: "将图片背景替换为{background},保持主体完整清晰,光影自然协调,边缘过渡平滑,保留主体阴影", negative: "残留原背景,边缘不自然,光影不协调,透视错误,主体变形", extractors: { background: /(?:换成|改成|替换为|变成|换为)(.+?)(?:背景|底|$)/, }, }, enhance: { template: "提升图片整体清晰度和质量,保持自然色彩不失真,去除噪点,增强细节,适度锐化", negative: "过度锐化,色彩失真,噪点增加,伪影,画质下降", extractors: {}, }, extend: { template: "向{direction}方向扩展图片{amount},保持原有风格和色调一致,光影过渡自然,无明显接缝", negative: "风格不一致,明显接缝,透视错误,内容突变", extractors: { direction: /向?(上|下|左|右|四周)/, amount: /(\d+%?)/, }, }, inpaint: { template: "去除/修改图片中的{target},用周围环境自然填充,保持整体风格一致,无修复痕迹", negative: "明显修复痕迹,风格不一致,内容错误,边缘不自然", extractors: { target: /(?:去除|消除|擦掉|删除|P掉)(.+?)(?:,|。|$)/, }, }, style_transfer: { template: "将图片转换为{style}风格,保持主体可识别性,色彩风格协调,整体效果自然", negative: "主体变形,特征丢失,风格不统一,色彩异常", extractors: { style: /(?:转换为|变成|改成)(.+?)(?:风格|$)/, }, }, resize: { template: "调整图片尺寸为{size},保持画质清晰,比例协调", negative: "画质损失,比例失调,模糊", extractors: { size: /(\d+[x×]\d+|\d+%)/, }, }, color_adjust: { template: "调整图片{adjustment},保持自然效果,色彩协调", negative: "色彩失真,过度调整,不自然", extractors: { adjustment: /(?:调整|增加|减少|提高|降低)(.+?)(?:,|。|$)/, }, }, }; /** * 优化提示词 */ export function optimizePrompt(params: { originalPrompt: string; intent: string; subIntent?: string; }): OptimizeResult { const { originalPrompt, intent, subIntent } = params; // 只对图片编辑类意图进行优化 if (intent !== "image_edit" || !subIntent) { return { originalPrompt, optimizedPrompt: originalPrompt, negativePrompt: "模糊,低质量,变形,水印", }; } const template = EDIT_TEMPLATES[subIntent]; if (!template) { return { originalPrompt, optimizedPrompt: originalPrompt, negativePrompt: "模糊,低质量,变形,水印", }; } // 使用模板生成优化后的提示词 let optimizedPrompt = template.template; // 从用户输入中提取参数并填充模板 for (const [key, regex] of Object.entries(template.extractors)) { const match = originalPrompt.match(regex); const value = match ? match[1].trim() : getDefaultValue(key); optimizedPrompt = optimizedPrompt.replace(`{${key}}`, value); } // 附加用户原始意图 optimizedPrompt = `${optimizedPrompt}。\n\n用户原始要求:${originalPrompt}`; console.log("[Prompt Optimizer] Optimized:", { original: originalPrompt, optimized: optimizedPrompt, negative: template.negative, }); return { originalPrompt, optimizedPrompt, negativePrompt: template.negative, }; } /** * 获取参数默认值 */ function getDefaultValue(key: string): string { const defaults: Record = { background: "纯白色", direction: "四周", amount: "50%", target: "指定区域", style: "卡通", size: "原尺寸", adjustment: "颜色", }; return defaults[key] || "默认"; } ``` ### 3.3 创建 `lib/ai/model-router.ts` ```typescript /** * 智能模型路由器 * 根据用户意图选择最佳模型 */ import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; // 路由结果类型 export interface RouteResult { id: string; displayName: string; providerType: string; reason: string; } // 意图到模型的映射配置 const INTENT_MODEL_MAP: Record< string, { providerTypes: string[]; requireVision?: boolean; requireImageGen?: boolean; } > = { // 图片编辑:优先 alibaba-image(灵魂4.5) image_edit: { providerTypes: ["alibaba-image", "gemini"], requireVision: true, requireImageGen: true, }, // 视觉理解:优先千问3 VL(成本低效果好) vision: { providerTypes: ["alibaba", "gemini"], requireVision: true, }, // 图片生成 image_gen: { providerTypes: ["alibaba-image", "gemini", "volcano-vision"], requireImageGen: true, }, // 视频生成 video_gen: { providerTypes: ["volcano-video", "qianwen-video"], }, // 普通对话 chat: { providerTypes: ["alibaba", "openai"], }, }; /** * 路由到最佳模型 */ export async function routeToModel(params: { intent: string; subIntent?: string; hasImage: boolean; }): Promise { const { intent, subIntent, hasImage } = params; console.log("[Model Router] Routing for intent:", intent, subIntent); // 获取所有可用模型 const allModels = await getEnabledAiModelsWithProvider(); // 获取意图对应的配置 const config = INTENT_MODEL_MAP[intent] || INTENT_MODEL_MAP["chat"]; // 按优先级查找匹配的模型 for (const providerType of config.providerTypes) { const candidates = allModels.filter((m) => { // 匹配 provider 类型 if (m.provider.type !== providerType) return false; // 检查能力要求 if (config.requireVision && !m.model.supportsVision) return false; if (config.requireImageGen && !m.model.supportsImageGen) return false; // 排除子模型 if (m.model.isSubModel) return false; // 必须启用 if (!m.model.isEnabled) return false; return true; }); if (candidates.length > 0) { // 优先选择默认模型 const defaultModel = candidates.find((c) => c.model.isDefault); const selected = defaultModel || candidates[0]; const result: RouteResult = { id: selected.model.id, displayName: selected.model.displayName, providerType: selected.provider.type, reason: `${intent}${subIntent ? `/${subIntent}` : ""} → ${selected.model.displayName}`, }; console.log("[Model Router] Selected:", result); return result; } } // 兜底:返回任意可用模型 const fallback = allModels.find((m) => !m.model.isSubModel && m.model.isEnabled) || allModels[0]; console.log("[Model Router] Using fallback model:", fallback.model.displayName); return { id: fallback.model.id, displayName: fallback.model.displayName, providerType: fallback.provider.type, reason: "fallback", }; } ``` ### 3.4 修改 `app/(chat)/api/chat/route.ts` 在现有的 Auto Mode 逻辑位置(约第 334-422 行),替换为以下代码: ```typescript // ========== Smart Auto Mode Logic ========== if (finalModelId === "auto") { console.log("[Smart Auto Mode] Starting intelligent analysis..."); // 1. 提取用户消息内容 const lastUserMessage = message; const textContent = lastUserMessage.parts .filter((p) => p.type === "text") .map((p) => (p as { type: "text"; text: string }).text) .join(" "); const hasImage = lastUserMessage.parts.some( (p) => p.type === "file" || p.type === "image" || p.type === "image_url" ); const imageUrls = lastUserMessage.parts .filter((p): p is { type: "file"; url: string } => p.type === "file") .map((p) => p.url); // 2. 调用智能分析器 const { analyzeIntent } = await import("@/lib/ai/smart-analyzer"); const analysisResult = await analyzeIntent({ text: textContent, hasImage, imageUrls, }); console.log("[Smart Auto Mode] Analysis result:", analysisResult); // 3. 如果需要澄清,返回澄清问题(可选功能) if (analysisResult.needsClarification && analysisResult.clarifyingQuestions) { console.log("[Smart Auto Mode] Needs clarification, but proceeding with best guess..."); // 暂时不中断流程,继续使用最佳猜测 } // 4. 如果是图片编辑类意图,优化提示词 if (analysisResult.intent === "image_edit" && analysisResult.subIntent) { const { optimizePrompt } = await import("@/lib/ai/prompt-optimizer"); const optimizedResult = optimizePrompt({ originalPrompt: textContent, intent: analysisResult.intent, subIntent: analysisResult.subIntent, }); console.log("[Smart Auto Mode] Prompt optimized"); // 替换消息中的文本为优化后的提示词 message.parts = message.parts.map((part) => { if (part.type === "text") { return { ...part, text: optimizedResult.optimizedPrompt, }; } return part; }); // 如果模型支持负面提示词,可以在 imageParams 中传递 // requestBody.imageParams = { // ...requestBody.imageParams, // negativePrompt: optimizedResult.negativePrompt, // }; } // 5. 路由到最佳模型 const { routeToModel } = await import("@/lib/ai/model-router"); const routeResult = await routeToModel({ intent: analysisResult.intent, subIntent: analysisResult.subIntent, hasImage, }); finalModelId = routeResult.id; console.log(`[Smart Auto Mode] ✅ Routed to: ${routeResult.displayName} (${routeResult.reason})`); } // ========== End Smart Auto Mode Logic ========== ``` --- ## 四、测试场景 ### 4.1 图片编辑场景测试 | 用户输入 | 预期意图 | 预期模型 | |---------|---------|---------| | [图片] + "帮我把背景换成白色" | replace_background | alibaba-image | | [图片] + "抠图" | remove_background | alibaba-image | | [图片] + "变清晰一点" | enhance | alibaba-image | | [图片] + "把右边的人P掉" | inpaint | alibaba-image | | [图片] + "转成卡通风格" | style_transfer | alibaba-image | ### 4.2 非编辑场景测试 | 用户输入 | 预期意图 | 预期模型 | |---------|---------|---------| | [图片] + "这是什么?" | vision | alibaba (Qwen3 VL) | | "画一个可爱的猫" | image_gen | alibaba-image | | "你好" | chat | alibaba (Qwen3 VL) | --- ## 五、开发步骤 ### Phase 1: 基础实现 (1-2天) 1. 创建 `lib/ai/smart-analyzer.ts` - 使用关键词匹配作为主逻辑 2. 创建 `lib/ai/prompt-optimizer.ts` - 实现模板化提示词优化 3. 创建 `lib/ai/model-router.ts` - 实现基于意图的模型路由 4. 修改 `app/(chat)/api/chat/route.ts` - 集成新模块 ### Phase 2: 智能升级 (2-3天) 1. 在 `smart-analyzer.ts` 中集成 Qwen3 VL 进行意图分析 2. 测试各种边界情况 3. 优化提示词模板 ### Phase 3: 反馈优化 (可选) 1. 添加用户反馈机制 2. 记录用户偏好 3. 持续优化模型路由策略 --- ## 六、注意事项 1. **保持向后兼容**:如果智能分析失败,自动回退到关键词匹配 2. **性能考虑**:Qwen3 分析会增加约 1-2 秒延迟,考虑是否需要 3. **错误处理**:所有新模块都需要完善的 try-catch 4. **日志记录**:添加详细日志便于调试 --- ## 七、文件结构 ``` lib/ └── ai/ ├── smart-analyzer.ts # 智能意图分析器 ├── prompt-optimizer.ts # 提示词优化器 ├── model-router.ts # 智能模型路由器 ├── dynamic-provider.ts # 现有模型提供器 └── providers/ # 现有模型提供商 ├── alibaba-image.ts ├── gemini-image.ts └── ... app/ └── (chat)/ └── api/ └── chat/ └── route.ts # 修改 Auto Mode 逻辑 ```