From 8763e8d53f38683c46f9090579cae0ba64fbb209 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 31 Jan 2026 23:15:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=99=BA=E8=83=BD=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E7=B3=BB=E7=BB=9F=20-=20=E6=84=8F=E5=9B=BE?= =?UTF-8?q?=E5=88=86=E6=9E=90=E3=80=81=E6=8F=90=E7=A4=BA=E8=AF=8D=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=81=E6=A8=A1=E5=9E=8B=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增智能自动模式功能: - smart-analyzer.ts: 智能意图分析器,识别抠图/换背景/增强等8种子意图 - prompt-optimizer.ts: 提示词优化器,将简单输入转为专业提示词 - model-router.ts: 智能模型路由器,根据意图选择最佳模型 - 修改route.ts集成新模块,替换原有关键词匹配逻辑 Co-authored-by: Cursor --- app/(chat)/api/chat/route.ts | 175 +- docs/smart-auto-implementation-guide.md | 755 +++++++++ docs/smart-auto-model-upgrade.md | 1960 +++++++++++++++++++++++ lib/ai/model-router.ts | 231 +++ lib/ai/prompt-optimizer.ts | 231 +++ lib/ai/smart-analyzer.ts | 347 ++++ 6 files changed, 3620 insertions(+), 79 deletions(-) create mode 100644 docs/smart-auto-implementation-guide.md create mode 100644 docs/smart-auto-model-upgrade.md create mode 100644 lib/ai/model-router.ts create mode 100644 lib/ai/prompt-optimizer.ts create mode 100644 lib/ai/smart-analyzer.ts diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 4d827169d..413e28b78 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -331,96 +331,113 @@ export async function POST(request: Request) { let finalModelId = selectedChatModel; - // ========== Auto Mode Logic ========== + // ========== Smart Auto Mode Logic ========== if (finalModelId === "auto") { - console.log("[Auto Mode] Detecting intent..."); - const lastUserMessage = message; - const textContent = lastUserMessage.parts - .filter((p) => p.type === 'text') - .map((p) => p.text) - .join(' '); - // @ts-ignore - const hasImage = lastUserMessage.parts.some((p) => p.type === 'file' || p.type === 'image' || p.type === 'image_url'); + console.log("[Smart Auto Mode] 🚀 Starting intelligent analysis..."); + + try { + // 1. 提取用户消息内容 + const lastUserMessage = message; + const textContent = lastUserMessage.parts + .filter((p): p is { type: "text"; text: string } => p.type === "text") + .map((p) => p.text) + .join(" "); - // 获取所有可用模型 - const allModels = await getEnabledAiModelsWithProvider(); - console.log("[Auto Mode] Available models:", allModels.map(m => `${m.model.displayName} (视频:${m.model.displayName.includes('视频')}, 图片:${m.model.supportsImageGen}, 视觉:${m.model.supportsVision})`)); - - let bestModel = null; + // @ts-ignore - 检查各种可能的图片类型 + const hasImage = lastUserMessage.parts.some( + (p: any) => p.type === "file" || p.type === "image" || p.type === "image_url" + ); - // 智能意图识别 - 基于关键词匹配 - // 定义各类意图的关键词库 - const videoKeywords = /(视频|video|movie|film|motion|mp4|avi|mov|wmv|flv|mkv|webm|m4v|生成视频|制作视频|创建视频|做视频|拍视频|录视频|录制|视频剪辑|剪辑视频|剪辑|编辑视频|sora|动起来|动画|animation|animate|animated|动态|动效|gif|clip|clips|短视频|长视频|影片|电影|微电影|宣传片|广告片|产品视频|演示视频|教程视频|mv|music video|片段|镜头|shot|场景|scene|特效|vfx|effects|转场|transition|字幕|subtitle|配音|dubbing|慢动作|快进|timelapse|延时)/i; - - const imageEditKeywords = /(修图|P图|改图|调图|优化图片|美化图片|处理图片|编辑图片|编辑照片|编辑这张|编辑|edit photo|edit image|修改图片|调整图片|图片处理|照片处理|处理这张|处理照片|背景|background|去背景|换背景|改背景|背景色|去背|抠图|扣图|抠出|扣出|去除|移除|删除|擦除|消除|抹掉|清除|拿掉|弄掉|去掉|干掉|隐藏|遮挡|remove|delete|erase|wipe|clear|eliminate|change|modify|修改|变清晰|清晰化|锐化|sharpen|sharpening|模糊|blur|blurry|虚化|bokeh|散景|修复|repair|restoration|fix|还原|恢复|recover|处理|process|processing|换|改|替换|更换|转换|transform|replace|swap|exchange|调色|调整颜色|color grade|grading|配色|滤镜|filter|filters|effect|特效|effects|裁剪|剪裁|crop|cropping|cut|cutting|旋转|rotate|rotation|翻转|flip|flipping|mirror|镜像|mirroring|缩放|resize|resizing|scale|scaling|放大|enlarge|enlargement|zoom|zoom in|缩小|shrink|zoom out|增强|enhance|enhancement|improve|improvement|提升|升级|质量|quality|降噪|去噪|denoise|denoising|美颜|beauty|磨皮|smooth|smoothing|瘦脸|face slim|美白|whitening|lighten|lighting|亮度|brightness|对比度|contrast|饱和度|saturation|曝光|exposure|高光|highlight|阴影|shadow|锐度|sharpness|加水印|去水印|watermark|unwatermark|合成|composite|compositing|拼接|拼图|merge|merging|叠加|overlay|blend|blending|透明|transparency|alpha|蒙版|mask|masking)/i; - - const imageGenKeywords = /(画|绘制|绘|绘画|画出|画个|画一个|画一张|画面|帮我画|给我画|画张|绘图|生成图片|生成图像|生成照片|生成一个|生成张|创建图片|创建图像|做图|制图|作图|画图|画画|想要.*图|需要.*图|来张|来个|draw|paint|sketch|素描|速写|render|rendering|渲染|picture|photo|image|图像|图片|照片|生图|出图|生成一张|生成|create image|generate image|make image|produce|design|designing|设计|设计一个|插画|illustration|illustrate|漫画|comic|卡通|cartoon|anime|动漫|二次元|海报|poster|logo|标志|商标|图标|icon|banner|横幅|背景图|背景|壁纸|wallpaper|桌面|配图|封面|cover|缩略图|thumbnail|头像|profile|avatar|artwork|艺术作品|art|artistic|美术|fine art|素材|material|asset|概念图|concept art|平面|graphic|graphics|视觉|visual|可视化|visualization|infographic|信息图)/i; - - const visionKeywords = /(看|看看|看一下|看下|识别|认出|辨认|recognize|identify|这是什么|是什么|what is|what\'s|分析|analyze|analysis|描述|describe|description|解释|explain|讲解|tell me|说说|介绍|理解|understand|检测|detect|detection|找|找出|find|发现|observe|观察|examine|检查|读取|read|阅读|翻译图片|ocr|文字识别|提取文字|图片.*内容|照片.*内容|image.*content)/i; - - if (videoKeywords.test(textContent)) { - console.log("[Auto Mode] Intent: VIDEO - 视频生成"); - bestModel = allModels.find(m => m.model.displayName.includes("视频")); - } - // 2. 图片编辑:用户上传了图片并要求编辑 - else if (hasImage && imageEditKeywords.test(textContent)) { - console.log("[Auto Mode] Intent: IMAGE_EDIT - 图片编辑"); - bestModel = allModels.find(m => m.model.displayName.includes("图片编辑") || m.model.displayName.includes("编辑")); - if (!bestModel) { - bestModel = allModels.find(m => m.model.supportsVision && !m.model.displayName.includes("视频")); + // @ts-ignore - 提取图片URL + const 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 }); + + // 2. 调用智能分析器 + const { analyzeIntent } = await import("@/lib/ai/smart-analyzer"); + const analysisResult = await analyzeIntent({ + text: textContent, + hasImage, + imageUrls, + }); + + console.log("[Smart Auto Mode] Analysis result:", { + intent: analysisResult.intent, + subIntent: analysisResult.subIntent, + confidence: analysisResult.confidence, + needsClarification: analysisResult.needsClarification, + }); + + // 3. 如果是图片编辑类意图,优化提示词 + 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:", { + original: textContent.substring(0, 50), + optimized: optimizedResult.optimizedPrompt.substring(0, 100), + }); + + // 替换消息中的文本为优化后的提示词 + message.parts = message.parts.map((part) => { + if (part.type === "text") { + return { + ...part, + text: optimizedResult.optimizedPrompt, + }; + } + return part; + }); } - } - // 3. 图片生成:用户要求画图/生成图片(不需要上传图片) - else if (imageGenKeywords.test(textContent)) { - console.log("[Auto Mode] Intent: IMAGE_GEN - 图片生成"); - bestModel = allModels.find(m => m.model.displayName.includes("图片编辑") || m.model.supportsImageGen); - // 排除视频模型 - if (bestModel && bestModel.model.displayName.includes("视频")) { - bestModel = allModels.find(m => (m.model.displayName.includes("图片编辑") || m.model.supportsImageGen) && !m.model.displayName.includes("视频")); + + // 4. 路由到最佳模型 + 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})`); + + } catch (autoError) { + // 智能分析失败时,回退到简单逻辑 + console.error("[Smart Auto Mode] ❌ Error, falling back:", autoError); + + const allModels = await getEnabledAiModelsWithProvider(); + // @ts-ignore - 检查各种可能的图片类型 + const hasImage = message.parts.some( + (p: any) => p.type === "file" || p.type === "image" || p.type === "image_url" + ); + + // 简单回退:有图选图片模型,无图选默认模型 + let bestModel = null; + if (hasImage) { + bestModel = allModels.find(m => m.model.supportsImageGen && !m.model.isSubModel); } - } - // 4. 多模态理解:用户上传了图片,想让AI看图理解内容 - else if (hasImage && visionKeywords.test(textContent)) { - console.log("[Auto Mode] Intent: VISION - 多模态理解"); - bestModel = allModels.find(m => m.model.displayName.includes("多模态") || m.model.supportsVision); if (!bestModel) { - bestModel = allModels.find(m => m.model.supportsVision && !m.model.displayName.includes("视频")); - } - } - // 5. 多模态理解:用户上传了图片但没有明确意图(默认理解图片) - else if (hasImage) { - console.log("[Auto Mode] Intent: VISION - 多模态理解(图片已上传)"); - bestModel = allModels.find(m => m.model.displayName.includes("多模态") || m.model.supportsVision); - if (!bestModel) { - bestModel = allModels.find(m => m.model.supportsVision); - } - } - // 6. 默认:普通文本对话 - else { - console.log("[Auto Mode] Intent: CHAT - 普通对话"); - // 优先使用多模态模型或默认模型 - bestModel = allModels.find(m => m.model.displayName.includes("多模态")); - if (!bestModel) { - bestModel = allModels.find(m => m.model.isDefault); + bestModel = allModels.find(m => m.model.isDefault && !m.model.isSubModel); } if (!bestModel && allModels.length > 0) { - bestModel = allModels[0]; + bestModel = allModels.find(m => !m.model.isSubModel) || allModels[0]; + } + + if (bestModel) { + finalModelId = bestModel.model.id; + console.log(`[Smart Auto Mode] Fallback selected: ${bestModel.model.displayName}`); + } else { + return new ChatSDKError("bad_request:api", "No available models for auto mode").toResponse(); } } - - // 最终兜底 - if (!bestModel && allModels.length > 0) { - bestModel = allModels.find(m => m.model.isDefault) || allModels[0]; - } - - if (bestModel) { - console.log(`[Auto Mode] ✅ Selected: ${bestModel.model.displayName} (${bestModel.model.id})`); - finalModelId = bestModel.model.id; - } else { - return new ChatSDKError("bad_request:api", "No available models for auto mode").toResponse(); - } } - // ========== End Auto Mode Logic ========== + // ========== End Smart Auto Mode Logic ========== const session = await auth(); diff --git a/docs/smart-auto-implementation-guide.md b/docs/smart-auto-implementation-guide.md new file mode 100644 index 000000000..7c9cfa825 --- /dev/null +++ b/docs/smart-auto-implementation-guide.md @@ -0,0 +1,755 @@ +# 智能图片编辑 - 实施开发指南 + +> 版本: 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 逻辑 +``` diff --git a/docs/smart-auto-model-upgrade.md b/docs/smart-auto-model-upgrade.md new file mode 100644 index 000000000..e3cbe0869 --- /dev/null +++ b/docs/smart-auto-model-upgrade.md @@ -0,0 +1,1960 @@ +# 智能自动模型系统升级开发文档 + +> 版本: v2.0 +> 日期: 2025-01-31 +> 参考: Lovart.ai 设计智能体架构、MagicQuill (CVPR 2025)、PromptEnhancer (腾讯混元) + +--- + +## 🎯 核心定位 + +**本系统主要应用于图片编辑场景,不是文生图。** + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 业务场景优先级 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ⭐⭐⭐ 图片编辑 (核心) │ +│ - 抠图/去背景 │ +│ - 换背景(纯色/场景) │ +│ - 图片增强/变清晰 │ +│ - 图像拓展 (Outpainting) │ +│ - 局部修改 (Inpainting) │ +│ - 风格迁移 │ +│ │ +│ ⭐⭐ 图片理解 (辅助) │ +│ - 图片内容分析 │ +│ - 对象识别 │ +│ │ +│ ⭐ 图片/视频生成 (辅助) │ +│ - 基于参考图生成 │ +│ - 图生视频 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 一、项目概述 + +### 1.1 现状分析 + +当前自动模型功能采用**基于关键词的规则匹配**方式: + +```typescript +// 当前实现 - app/(chat)/api/chat/route.ts +const videoKeywords = /(视频|video|动画|sora|动起来...)/i; +const imageEditKeywords = /(修图|P图|去背景|抠图...)/i; +const imageGenKeywords = /(画|绘制|生成图片|海报...)/i; + +if (videoKeywords.test(textContent)) { + bestModel = allModels.find(m => m.model.displayName.includes("视频")); +} +``` + +**存在的问题:** +- ❌ 规则硬编码,扩展性差 +- ❌ 无法理解复杂/模糊的用户意图 +- ❌ 提示词质量完全依赖用户 +- ❌ 无法学习用户偏好 +- ❌ 不支持多轮对话细化 + +### 1.2 核心应用场景:图片编辑 + +**我们的主要业务是图片编辑,不是文生图。** 主要场景包括: + +| 场景 | 描述 | 对应模型能力 | +|-----|------|-------------| +| **抠图/去背景** | 去除图片背景,保留主体 | image_edit + vision | +| **换背景** | 替换为新背景(纯色/场景) | image_edit | +| **图片增强** | 变清晰、降噪、提升质量 | image_edit | +| **图像拓展** | Outpainting,扩展画布边界 | image_edit | +| **局部修改** | Inpainting,修改特定区域 | image_edit + vision | +| **尺寸调整** | 裁剪、缩放、调整比例 | resize (工具) | +| **角度调整** | 旋转、翻转、透视变换 | angle_edit (工具) | +| **风格迁移** | 改变图片风格(卡通化等) | image_edit | +| **图片理解** | 分析图片内容、识别对象 | vision | +| **生图辅助** | 基于参考图生成新图 | image_gen | + +### 1.3 升级目标 + +参考 Lovart.ai 的设计智能体架构,构建**基于 LLM 的智能图片编辑系统**: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 智能自动模型系统 v2.0 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ 用户输入 ──▶ Qwen3 多模态分析 ──▶ 智能模型路由 ──▶ 生成模型 │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ 意图识别 + 语义分解 最优模型选择 提示词优化执行 │ +│ (8个设计维度分析) (多因素评分) (专业级提示词) │ +│ │ │ │ │ +│ └──────────┬───────┘ │ │ +│ ▼ ▼ │ +│ 用户偏好学习系统 ◀──── 反馈迭代优化 │ +│ (贝叶斯优化/记忆) │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**核心升级:** +- ✅ 使用 Qwen3 进行智能意图分析 +- ✅ 自动优化/扩写用户提示词 +- ✅ 基于多因素评分的模型路由 +- ✅ 用户偏好学习与记忆 +- ✅ 支持多轮对话细化 + +--- + +## 1.3 当前已配置的模型清单 + +### 模型提供商 (AiProvider) + +| 名称 | 类型 (providerType) | API 地址 | 用途 | +|-----|---------------------|----------|------| +| 阿里云 | `alibaba` | dashscope.aliyuncs.com | 对话模型 | +| 千问生图 | `alibaba-image` | dashscope.aliyuncs.com | 阿里图片生成 | +| Gemini中转 | `gemini` | grsai.dakka.com.cn | Gemini 图片生成 | +| 既梦模型 | `volcano-vision` | ark.cn-beijing.volces.com | 火山图片生成 | +| 火山引擎视频 | `volcano-video` | ark.cn-beijing.volces.com | 视频生成 | +| 千问视频 | `qianwen-video` | dashscope.aliyuncs.com | 阿里视频生成 | +| 千问本地模型 | `local` | 156.225.27.52:8001 | 本地部署 | +| 环科API | `openai` | api.huandutech.com | OpenAI 兼容 | + +### 已启用的模型 (AiModel) + +| 显示名称 | modelId | 提供商类型 | 能力 | 配置 | +|---------|---------|-----------|------|------| +| **千问3「对话模型」** | qwen3-vl-plus | alibaba | 对话 | 默认模型 | +| **既梦4.5「生图模型」** | doubao-seedream-4-5-251128 | volcano-vision | 图片生成 | 火山既梦 | +| **VIDEO「视频模型」** | volcano-video-master | volcano-video | 视频生成 | 支持多模式 | +| **GTP1.5「生图模型」** | gpt-image-1.5 | gemini | 视觉理解 | Gemini 中转 | +| **香蕉PRO「生图模型」** | nano-banana-pro | gemini | 视觉+图片生成 | 最大2张图 | +| **灵魂4.5「生图模型」** | qwen-image-edit-max-2026-01-16 | alibaba-image | 视觉+图片生成 | 支持提示词扩展 | +| **SeedancePro** | doubao-seedance-1-0-pro-250528 | volcano-video | 视频生成 | 专业版,1080p | +| **SeedanceProFast** | doubao-seedance-1-0-pro-fast-251015 | volcano-video | 视频生成 | 快速版 | +| **SeedanceLiteI2V** | doubao-seedance-1-0-lite-i2v-250428 | volcano-video | 视频生成 | 图生视频轻量版 | +| **SeedanceLiteT2V** | doubao-seedance-1-0-lite-t2v-250428 | volcano-video | 视频生成 | 文生视频轻量版 | + +### 模型能力矩阵 + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ 模型能力矩阵 │ +├────────────────────┬─────────┬─────────┬─────────┬─────────┬──────────────┤ +│ 模型 │ 对话 │ 视觉理解 │ 图片生成 │ 视频生成 │ 图片编辑 │ +├────────────────────┼─────────┼─────────┼─────────┼─────────┼──────────────┤ +│ 千问3 (VL) │ ✅ │ ✅ │ ❌ │ ❌ │ ❌ │ +│ 既梦4.5 │ ❌ │ ❌ │ ✅ │ ❌ │ ❌ │ +│ GTP1.5 │ ❌ │ ✅ │ ❌ │ ❌ │ ❌ │ +│ 香蕉PRO │ ❌ │ ✅ │ ✅ │ ❌ │ ✅ │ +│ 灵魂4.5 │ ❌ │ ✅ │ ✅ │ ❌ │ ✅ │ +│ VIDEO │ ❌ │ ✅ │ ❌ │ ✅ │ ❌ │ +│ SeedancePro │ ❌ │ ✅ │ ❌ │ ✅ │ ❌ │ +│ SeedanceProFast │ ❌ │ ✅ │ ❌ │ ✅ │ ❌ │ +│ SeedanceLiteI2V │ ❌ │ ✅ │ ❌ │ ✅ │ ❌ │ +│ SeedanceLiteT2V │ ❌ │ ❌ │ ❌ │ ✅ │ ❌ │ +└────────────────────┴─────────┴─────────┴─────────┴─────────┴──────────────┘ + +注:千问3 使用的是 qwen3-vl-plus 模型,VL = Vision-Language,是阿里云的多模态模型, + 既支持纯文本对话,也支持图片理解分析。 +``` + +### 智能路由映射策略 (图片编辑优先) + +根据用户意图,智能路由到最佳模型: + +| 意图 | 优先级 | 首选模型 | 备选模型 | 路由逻辑 | +|-----|-------|---------|---------|---------| +| **图片编辑** | ⭐⭐⭐ | 灵魂4.5 | 香蕉PRO | 核心业务,supportsVision + supportsImageGen | +| **视觉理解** | ⭐⭐ | 千问3 (VL) | GTP1.5 | 千问3成本更低,效果也好 | +| **图片生成** | ⭐⭐ | 灵魂4.5 | 香蕉PRO / 既梦4.5 | 支持提示词扩展优先 | +| **视频生成** | ⭐ | VIDEO (Master) | SeedancePro | 自动选择子模型 | +| **图生视频** | ⭐ | SeedanceLiteI2V | SeedancePro | 有图片输入 | +| **普通对话** | - | 千问3 (VL) | - | 默认对话模型 | + +### 图片编辑子意图路由 + +| 子意图 | 最佳模型 | 原因 | +|-------|---------|------| +| remove_background | 灵魂4.5 / 香蕉PRO | 支持精准抠图 | +| replace_background | 灵魂4.5 | 支持场景生成 | +| enhance | 灵魂4.5 / 既梦4.5 | 高质量增强 | +| extend (outpainting) | 灵魂4.5 | 支持画布扩展 | +| inpaint | 灵魂4.5 / 香蕉PRO | 精准局部编辑 | +| style_transfer | 香蕉PRO / 灵魂4.5 | 风格迁移能力 | +| resize/crop | 工具处理 | 不需要AI模型 | +| color_adjust | 工具处理 | 不需要AI模型 | + +**重要说明:** +- **图片编辑是核心业务**,优先保证编辑类意图的识别准确性 +- **灵魂4.5 (alibaba-image)** 是图片编辑的首选,支持提示词扩展 +- **千问3 (VL)** 用于图片理解分析,成本低效果好 +- **resize/crop/color_adjust** 等简单操作由前端工具直接处理,不需要调用 AI 模型 + +--- + +## 二、聊天对话框中的图片编辑流程设计 + +### 2.1 当前系统数据流分析 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ 当前系统数据流 │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 用户在对话框中 │ +│ │ │ +│ ▼ │ +│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ MultimodalInput │───▶│ Chat 组件 │───▶│ sendMessage() │ │ +│ │ (前端组件) │ │ 状态管理 │ │ 发送消息 │ │ +│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ +│ │ │ │ +│ │ 用户输入: │ │ +│ │ - 图片附件 (attachments) │ │ +│ │ - 文字描述 (input) │ │ +│ │ - 选择的模型 (selectedModelId) ▼ │ +│ │ ┌─────────────────────┐ │ +│ │ │ POST /api/chat │ │ +│ │ │ (route.ts) │ │ +│ │ └─────────────────────┘ │ +│ │ │ │ +│ │ ▼ │ +│ │ ┌─────────────────────┐ │ +│ │ │ Auto Mode 检测 │ │ +│ │ │ (关键词匹配) │ │ +│ │ └─────────────────────┘ │ +│ │ │ │ +│ │ ▼ │ +│ │ ┌─────────────────────┐ │ +│ │ │ 路由到对应模型 │ │ +│ │ │ - gemini-image │ │ +│ │ │ - alibaba-image │ │ +│ │ │ - volcano-vision │ │ +│ │ └─────────────────────┘ │ +│ │ │ │ +│ │ ▼ │ +│ │ ┌─────────────────────┐ │ +│ │ │ 模型生成结果 │ │ +│ │ │ 返回 Markdown 图片 │ │ +│ │ └─────────────────────┘ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Messages 组件渲染结果 │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 升级后的智能图片编辑流程 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ 智能图片编辑升级流程 │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 用户在对话框中输入 │ +│ ┌──────────────────────────────────────┐ │ +│ │ 📸 上传图片 │ │ +│ │ 💬 "帮我把背景换成白色" │ │ +│ │ 📤 发送 │ │ +│ └──────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Phase 1: 智能意图分析器 (Smart Analyzer) │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ 使用 Qwen3 VL 分析: │ │ │ +│ │ │ - 检测用户意图: replace_background │ │ │ +│ │ │ - 分析图片内容: 产品图,背景杂乱 │ │ │ +│ │ │ - 置信度: 0.95 │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Phase 2: 提示词优化器 (Prompt Optimizer) │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ 用户原始: "帮我把背景换成白色" │ │ │ +│ │ │ ▼ │ │ │ +│ │ │ 优化后: "将图片背景替换为纯白色(#FFFFFF),保留产品主体, │ │ │ +│ │ │ 保持自然阴影效果,边缘处理平滑自然" │ │ │ +│ │ │ │ │ │ +│ │ │ 负面提示: "模糊边缘,残留背景,阴影不自然,过曝" │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Phase 3: 智能模型路由器 (Model Router) │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ 意图: replace_background │ │ │ +│ │ │ 推荐模型: alibaba-image (灵魂4.5) │ │ │ +│ │ │ 原因: 支持高质量背景替换,提示词扩展能力强 │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Phase 4: 执行图片编辑 │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ 调用 alibaba-image API: │ │ │ +│ │ │ - 输入图片: 用户上传的原图 │ │ │ +│ │ │ - 优化后提示词: "将图片背景替换为纯白色..." │ │ │ +│ │ │ - 负面提示词: "模糊边缘..." │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ 返回结果到对话框 │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ 🤖 助手回复: │ │ │ +│ │ │ "已将背景替换为白色,保留了产品的自然阴影效果。" │ │ │ +│ │ │ │ │ │ +│ │ │ [编辑后的图片] │ │ │ +│ │ │ │ │ │ +│ │ │ 💡 提示: 如需调整,可以说"阴影深一点"或"边缘更清晰" │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### 2.3 关键代码位置说明 + +#### 前端代码 + +| 文件 | 作用 | 需要修改的内容 | +|-----|------|---------------| +| `components/multimodal-input.tsx` | 用户输入组件 | 无需大改,已支持图片+文字发送 | +| `components/chat.tsx` | 聊天状态管理 | 添加意图分析结果展示(可选) | +| `components/messages.tsx` | 消息渲染 | 无需修改,已支持图片渲染 | + +#### 后端代码 + +| 文件 | 作用 | 需要修改的内容 | +|-----|------|---------------| +| `app/(chat)/api/chat/route.ts` | 聊天API入口 | **核心修改点** - 集成智能分析器和路由器 | +| `lib/ai/smart-analyzer.ts` | 智能意图分析器 | **新建** - Qwen3 意图分析 | +| `lib/ai/prompt-optimizer.ts` | 提示词优化器 | **新建** - 提示词增强 | +| `lib/ai/model-router.ts` | 模型路由器 | **新建** - 智能模型选择 | + +### 2.4 详细实现方案 + +#### 2.4.1 修改 route.ts 的 Auto Mode 逻辑 + +**当前代码** (route.ts 第 334-422 行): +```typescript +// ========== Auto Mode Logic ========== +if (finalModelId === "auto") { + console.log("[Auto Mode] Detecting intent..."); + // 使用关键词匹配... + const videoKeywords = /视频|video.../; + const imageEditKeywords = /修图|P图.../; + // ... +} +``` + +**升级后代码**: +```typescript +// ========== Smart Auto Mode Logic ========== +if (finalModelId === "auto") { + console.log("[Smart Auto Mode] Starting intelligent analysis..."); + + // 1. 调用智能分析器 + const { analyzeIntent } = await import("@/lib/ai/smart-analyzer"); + const analysisResult = await analyzeIntent({ + text: textContent, + hasImage, + imageUrls: extractImageUrls(lastUserMessage), + }); + + console.log("[Smart Auto Mode] Analysis result:", analysisResult); + + // 2. 如果是图片编辑类意图,优化提示词 + if (analysisResult.intent.startsWith("image_edit")) { + const { optimizePrompt } = await import("@/lib/ai/prompt-optimizer"); + const optimizedResult = await optimizePrompt({ + originalPrompt: textContent, + intent: analysisResult.intent, + subIntent: analysisResult.subIntent, + }); + + // 替换用户消息中的文本为优化后的提示词 + message.parts = message.parts.map(part => { + if (part.type === "text") { + return { ...part, text: optimizedResult.optimizedPrompt }; + } + return part; + }); + + console.log("[Smart Auto Mode] Prompt optimized:", optimizedResult.optimizedPrompt); + } + + // 3. 路由到最佳模型 + const { routeToModel } = await import("@/lib/ai/model-router"); + const selectedModel = await routeToModel({ + intent: analysisResult.intent, + subIntent: analysisResult.subIntent, + hasImage, + }); + + finalModelId = selectedModel.id; + console.log(`[Smart Auto Mode] ✅ Routed to: ${selectedModel.displayName}`); +} +``` + +#### 2.4.2 新建 smart-analyzer.ts + +```typescript +// lib/ai/smart-analyzer.ts + +import { getLanguageModelById } from "./dynamic-provider"; +import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; + +export interface AnalysisResult { + intent: string; // 主意图: image_edit, vision, image_gen, video_gen, chat + subIntent?: string; // 子意图: remove_background, replace_background, enhance 等 + confidence: number; // 置信度 0-1 + optimizedPrompt?: string; // 优化后的提示词(可选) + negativePrompt?: string; // 负面提示词(可选) + suggestedModel?: string; // 推荐模型ID +} + +const ANALYZER_SYSTEM_PROMPT = `你是图片编辑意图分析专家。分析用户输入,返回JSON格式结果。 + +## 图片编辑子意图(核心,优先识别) +- remove_background: 抠图、去背景、透明背景 +- replace_background: 换背景、改背景、白底、场景替换 +- enhance: 变清晰、高清、锐化、降噪、提升质量 +- extend: 扩展、拓展、outpainting +- inpaint: 去除XX、消除、擦掉、修改局部 +- style_transfer: 风格化、卡通化、动漫风 +- resize: 缩放、裁剪、调整尺寸 +- color_adjust: 调色、调整颜色、亮度、对比度 + +## 输出格式(严格JSON) +{ + "intent": "image_edit", + "subIntent": "replace_background", + "confidence": 0.95, + "optimizedPrompt": "将图片背景替换为纯白色(#FFFFFF),保留产品主体完整,保持自然阴影,边缘处理平滑自然", + "negativePrompt": "模糊边缘,残留背景,阴影不自然,过曝,变形" +}`; + +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) { + // 回退到关键词匹配 + return fallbackKeywordAnalysis(text, hasImage); + } + + const model = await getLanguageModelById(qwenModel.model.id); + if (!model) { + return fallbackKeywordAnalysis(text, hasImage); + } + + try { + // 构建消息 + const messages = [ + { role: "system", content: ANALYZER_SYSTEM_PROMPT }, + { + role: "user", + content: hasImage + ? `用户上传了图片,请求: "${text}"` + : `用户请求(无图片): "${text}"` + } + ]; + + // 调用千问3分析 + const response = await model.doGenerate({ + messages, + temperature: 0.1, // 低温度保证稳定输出 + }); + + // 解析JSON响应 + const jsonMatch = response.text.match(/\{[\s\S]*\}/); + if (jsonMatch) { + return JSON.parse(jsonMatch[0]); + } + } 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: "vision", confidence: 0.8 }; + } + + // 有图但无明确意图 → 默认为编辑 + return { intent: "image_edit", confidence: 0.5 }; + } + + // 无图 → 生成或对话 + if (/画|绘制|生成图/.test(lowerText)) { + return { intent: "image_gen", confidence: 0.8 }; + } + + return { intent: "chat", confidence: 0.7 }; +} +``` + +#### 2.4.3 新建 prompt-optimizer.ts + +```typescript +// lib/ai/prompt-optimizer.ts + +export interface OptimizeResult { + originalPrompt: string; + optimizedPrompt: string; + negativePrompt: string; +} + +// 图片编辑子意图的提示词模板 +const EDIT_TEMPLATES: Record = { + remove_background: { + template: "去除图片背景,保留主体{subject},输出透明背景,边缘处理平滑自然,保留细节", + negative: "残留背景,毛边,边缘模糊,主体不完整" + }, + replace_background: { + template: "将图片背景替换为{background},保持主体完整,光影自然协调,边缘过渡平滑", + negative: "残留原背景,边缘不自然,光影不协调,透视错误" + }, + enhance: { + template: "提升图片整体清晰度和质量,保持自然色彩,去除噪点,增强细节", + negative: "过度锐化,色彩失真,噪点,伪影" + }, + extend: { + template: "向{direction}方向扩展图片{amount},保持原有风格和色调一致,光影过渡自然", + negative: "风格不一致,明显接缝,透视错误" + }, + inpaint: { + template: "去除/修改图片中的{target},用周围环境自然填充,保持整体风格一致", + negative: "明显修复痕迹,风格不一致,内容错误" + }, + style_transfer: { + template: "将图片转换为{style}风格,保持主体可识别性,色彩风格协调", + negative: "主体变形,特征丢失,风格不统一" + } +}; + +export async function optimizePrompt(params: { + originalPrompt: string; + intent: string; + subIntent?: string; +}): Promise { + 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; + + // 提取背景描述(换背景场景) + if (subIntent === "replace_background") { + const bgMatch = originalPrompt.match(/(?:换成|改成|替换为|变成)(.+?)(?:背景|$)/); + const background = bgMatch ? bgMatch[1].trim() : "纯白色"; + optimizedPrompt = optimizedPrompt.replace("{background}", background); + } + + // 提取扩展方向和数量(扩展场景) + if (subIntent === "extend") { + const dirMatch = originalPrompt.match(/向?(上|下|左|右)/); + const direction = dirMatch ? dirMatch[1] : "四周"; + const amountMatch = originalPrompt.match(/(\d+%?)/); + const amount = amountMatch ? amountMatch[1] : "50%"; + optimizedPrompt = optimizedPrompt + .replace("{direction}", direction) + .replace("{amount}", amount); + } + + // 提取目标对象(局部修改场景) + if (subIntent === "inpaint") { + const targetMatch = originalPrompt.match(/(?:去除|消除|擦掉|删除)(.+?)(?:,|。|$)/); + const target = targetMatch ? targetMatch[1].trim() : "指定区域"; + optimizedPrompt = optimizedPrompt.replace("{target}", target); + } + + // 提取风格(风格迁移场景) + if (subIntent === "style_transfer") { + const styleMatch = originalPrompt.match(/(?:转换为|变成|改成)(.+?)(?:风格|$)/); + const style = styleMatch ? styleMatch[1].trim() : "卡通"; + optimizedPrompt = optimizedPrompt.replace("{style}", style); + } + + return { + originalPrompt, + optimizedPrompt: `${optimizedPrompt}。用户原始要求:${originalPrompt}`, + negativePrompt: template.negative + }; +} +``` + +#### 2.4.4 新建 model-router.ts + +```typescript +// lib/ai/model-router.ts + +import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; + +export interface RouteResult { + id: string; + displayName: string; + providerType: string; + reason: string; +} + +// 意图到模型的映射配置 +const INTENT_MODEL_MAP: Record = { + // 图片编辑:优先 alibaba-image + "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; + + // 获取所有可用模型 + 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; + + return true; + }); + + if (candidates.length > 0) { + // 优先选择默认模型 + const defaultModel = candidates.find(c => c.model.isDefault); + const selected = defaultModel || candidates[0]; + + return { + id: selected.model.id, + displayName: selected.model.displayName, + providerType: selected.provider.type, + reason: `意图 ${intent}${subIntent ? `/${subIntent}` : ''} → ${selected.model.displayName}` + }; + } + } + + // 兜底:返回任意可用模型 + const fallback = allModels.find(m => !m.model.isSubModel) || allModels[0]; + return { + id: fallback.model.id, + displayName: fallback.model.displayName, + providerType: fallback.provider.type, + reason: "fallback" + }; +} +``` + +### 2.5 用户体验流程 + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ 用户交互流程 │ +├────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1️⃣ 用户选择模型: │ +│ ┌─────────────────────┐ │ +│ │ ✨ 智能自动 (Auto) │ ← 默认选项,推荐使用 │ +│ │ 灵魂4.5 (图片编辑) │ │ +│ │ 香蕉PRO │ │ +│ │ 千问3 VL │ │ +│ └─────────────────────┘ │ +│ │ +│ 2️⃣ 用户上传图片 + 输入文字: │ +│ ┌─────────────────────────────────────────┐ │ +│ │ [📸 产品图.jpg] │ │ +│ │ │ │ +│ │ 帮我把背景换成白色 _______________ 📤 │ │ +│ └─────────────────────────────────────────┘ │ +│ │ +│ 3️⃣ 系统处理(后台透明执行): │ +│ ┌─────────────────────────────────────────┐ │ +│ │ 🔍 分析意图: replace_background (95%) │ │ +│ │ ✨ 优化提示词... │ │ +│ │ 🚀 路由到: 灵魂4.5 │ │ +│ │ ⏳ 生成中... │ │ +│ └─────────────────────────────────────────┘ │ +│ │ +│ 4️⃣ 返回结果: │ +│ ┌─────────────────────────────────────────┐ │ +│ │ 🤖 助手: │ │ +│ │ │ │ +│ │ 已将背景替换为白色。 │ │ +│ │ │ │ +│ │ [编辑后的图片预览] │ │ +│ │ │ │ +│ │ 📥 下载原图 🔄 重新生成 │ │ +│ └─────────────────────────────────────────┘ │ +│ │ +└────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 三、技术架构 + +### 2.1 整体架构图 + +``` +┌──────────────────────────────────────────────────────────────────────────┐ +│ 客户端层 │ +├──────────────────────────────────────────────────────────────────────────┤ +│ MultimodalInput ──▶ 选择"智能自动"模型 ──▶ 发送消息 │ +└──────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────┐ +│ API 网关层 │ +├──────────────────────────────────────────────────────────────────────────┤ +│ /api/chat/route.ts │ +│ │ │ +│ ├─▶ 检测 modelId === "auto" │ +│ │ │ +│ └─▶ 调用智能分析服务 ────────────────────────────────────────┐ │ +└──────────────────────────────────────────────────────────────────────────┘ + │ │ + ▼ ▼ +┌──────────────────────────────────────────────────────────────────────────┐ +│ 智能分析服务层 (新增) │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ 意图分析模块 │ │ 提示词优化模块 │ │ 模型路由模块 │ │ +│ │ │ │ │ │ │ │ +│ │ - 意图分类 │ │ - 维度分解 │ │ - 多因素评分 │ │ +│ │ - 置信度评估 │ │ - 专业词汇注入 │ │ - 能力匹配 │ │ +│ │ - 澄清问题生成 │ │ - 质量关键词 │ │ - 负载均衡 │ │ +│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ +│ │ │ │ │ +│ └────────────────────┼────────────────────┘ │ +│ ▼ │ +│ ┌─────────────────────┐ │ +│ │ Qwen3 多模态模型 │ │ +│ │ (qwen3-turbo) │ │ +│ └─────────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────┐ +│ 生成模型执行层 │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ +│ │ Gemini 2.0 │ │ 阿里万象 │ │ 火山视频 │ │ Qwen-VL │ │ +│ │ Flash │ │ 图片生成 │ │ 生成模型 │ │ 多模态 │ │ +│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────┐ +│ 用户偏好学习层 (新增) │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ 反馈收集 │ │ 偏好分析 │ │ 上下文记忆 │ │ +│ │ │ │ │ │ │ │ +│ │ - 显式反馈 │ │ - 风格偏好 │ │ - 历史提示词 │ │ +│ │ - 隐式反馈 │ │ - 色彩偏好 │ │ - 常用风格 │ │ +│ │ - 重新生成统计 │ │ - 质量偏好 │ │ - 决策点追踪 │ │ +│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 核心模块设计 + +#### 2.2.1 意图分析模块 + +**输入:** +- 用户文本输入 +- 是否有图片附件 +- 对话历史 (上下文) + +**输出:** +```typescript +interface IntentAnalysis { + // 意图类型 + intent: "image_gen" | "image_edit" | "video_gen" | "vision" | "chat"; + + // 意图置信度 (0-1) + confidence: number; + + // 子意图 (更细粒度) + subIntent?: string; // 如 "remove_background", "enhance_quality", "style_transfer" + + // 是否需要澄清 + needsClarification: boolean; + + // 澄清问题 (如果需要) + clarifyingQuestions?: string[]; +} +``` + +#### 2.2.2 提示词优化模块 + +**设计维度分解 (参考 Lovart 的 12 维度):** + +| 维度 | 英文 | 描述 | 示例 | +|-----|------|------|------| +| 主体 | subject | 画面的主要对象 | "一只橘色的猫" | +| 动作 | action | 主体的姿态或行为 | "慵懒地躺着" | +| 风格 | style | 艺术风格 | "写实摄影风格" | +| 光影 | lighting | 光照效果 | "柔和的自然光" | +| 构图 | composition | 画面构图 | "中景特写" | +| 色彩 | color | 色彩方案 | "暖色调" | +| 氛围 | mood | 情绪氛围 | "温馨舒适" | +| 质量 | quality | 质量关键词 | "8K, 高细节" | + +**输出:** +```typescript +interface PromptOptimization { + // 维度分解 + dimensions: { + subject: string; + action: string; + style: string; + lighting: string; + composition: string; + color: string; + mood: string; + quality: string; + }; + + // 维度权重 (重要程度) + weights: Record; + + // 优化后的完整提示词 + optimizedPrompt: string; + + // 负面提示词 (需要避免的) + negativePrompt?: string; +} +``` + +#### 2.2.3 模型路由模块 + +**多因素评分算法:** + +```typescript +interface ModelScore { + modelId: string; + scores: { + intentMatch: number; // 意图匹配度 (0-50) + styleMatch: number; // 风格匹配度 (0-20) + qualityMatch: number; // 质量能力匹配 (0-15) + costEfficiency: number; // 成本效益 (0-10) + loadBalance: number; // 负载均衡 (0-5) + }; + totalScore: number; +} +``` + +--- + +## 三、实现计划 + +### Phase 1: 核心功能 (MVP) + +**目标:** 实现 Qwen3 意图分析 + 提示词优化 + +**新增文件:** +``` +lib/ +├── ai/ +│ ├── smart-analyzer.ts # 智能分析核心逻辑 +│ ├── prompt-optimizer.ts # 提示词优化器 +│ └── model-router.ts # 模型路由器 +│ +app/ +├── api/ +│ └── smart-analyze/ +│ └── route.ts # 智能分析 API +``` + +**修改文件:** +``` +app/(chat)/api/chat/route.ts # 集成智能分析 +``` + +#### 3.1.1 智能分析器 (`lib/ai/smart-analyzer.ts`) + +```typescript +import { createOpenAI } from "@ai-sdk/openai"; +import { generateText } from "ai"; + +// Qwen3 客户端配置 +const qwen = createOpenAI({ + baseURL: process.env.QWEN_API_BASE_URL, + apiKey: process.env.QWEN_API_KEY, +}); + +// 系统提示词 - 针对当前系统模型配置优化 +const ANALYZER_SYSTEM_PROMPT = `你是一个专业的 AI 设计助手,负责分析用户意图并优化提示词。 + +## 你的任务 +1. 分析用户输入的意图类型 +2. 将模糊描述分解为 8 个专业设计维度 +3. 生成优化后的高质量提示词 +4. 推荐最适合的生成模型 + +## 当前系统可用的模型 +| 模型名称 | 类型 | 能力 | 适用场景 | +|---------|------|------|---------| +| 千问3 (VL) | alibaba | 对话+视觉理解 | 普通对话、看图问答、图片分析 | +| 灵魂4.5 | alibaba-image | 图片生成+编辑 | 高质量图片生成,支持提示词扩展 | +| 香蕉PRO | gemini | 图片生成+视觉 | 图片生成、图片编辑 | +| 既梦4.5 | volcano-vision | 图片生成 | 快速图片生成 | +| GTP1.5 | gemini | 视觉理解 | 图片分析、识别 | +| VIDEO | volcano-video | 视频生成 | 文生视频、图生视频 | + +注意:千问3 使用的是 qwen3-vl-plus 多模态模型,VL = Vision-Language,既支持文本对话也支持图片理解。 + +## 意图类型定义(图片编辑为主) + +### 核心意图:图片编辑 (image_edit) - 最高优先级 +用户上传了图片,并希望对其进行编辑修改。 + +| 子意图 | 触发词 | 说明 | +|-------|-------|------| +| remove_background | 抠图、去背景、去背、扣图、透明背景 | 去除背景保留主体 | +| replace_background | 换背景、改背景、背景换成、场景替换 | 替换为新背景 | +| enhance | 变清晰、高清、锐化、降噪、提升质量、修复 | 图片增强 | +| extend | 扩展、拓展、延伸、outpainting、扩图 | 图像边界拓展 | +| inpaint | 去除XX、消除、擦掉、修改XX部分、局部修改 | 局部区域修改 | +| style_transfer | 风格化、卡通化、动漫风、油画风、改风格 | 风格迁移 | +| resize | 缩放、放大、缩小、调整尺寸、裁剪 | 尺寸调整 | +| color_adjust | 调色、调整颜色、亮度、对比度、饱和度 | 颜色调整 | + +推荐模型:alibaba-image(灵魂4.5)或 gemini(香蕉PRO) + +### 辅助意图:图片理解 (vision) +用户上传了图片,想要理解/分析其内容(不涉及编辑)。 + +触发词:看、识别、分析、描述、这是什么、有什么、tell me、what is this +推荐模型:alibaba(千问3 VL,成本低效果好) + +### 辅助意图:图片生成 (image_gen) +用户想要生成新图片(无需上传图片,或基于参考图生成)。 + +触发词:画、绘制、生成图片、创建、设计 +推荐模型:alibaba-image(灵魂4.5) + +### 辅助意图:视频生成 (video_gen) +用户想要将图片转为视频或生成视频。 + +触发词:视频、动画、动起来、让它动 +推荐模型:volcano-video + +### 默认意图:对话 (chat) +普通文字对话,不涉及图像处理。 + +推荐模型:alibaba(千问3 VL) + +## 提示词优化公式 + +### 图片编辑场景(核心) +针对不同编辑子意图,优化提示词的重点不同: + +| 子意图 | 提示词重点 | 示例优化 | +|-------|----------|---------| +| remove_background | 描述主体特征 | "保留产品主体,去除所有背景,输出透明PNG" | +| replace_background | 描述新背景细节 | "将背景替换为白色纯色背景,保持产品阴影" | +| enhance | 描述增强程度和方向 | "提升图片清晰度,保持自然色彩,去除噪点" | +| extend | 描述扩展方向和内容 | "向右扩展50%,保持原有风格和光影一致性" | +| inpaint | 精确描述修改区域 | "去除图片右上角的水印,用周围纹理自然填充" | +| style_transfer | 描述目标风格 | "将照片转换为吉卜力动画风格,保持人物特征" | + +### 图片生成场景(辅助) +[主体 Subject] + [动作 Action] + [风格 Style] + [光影 Lighting] + [构图 Composition] + [色彩 Color] + [氛围 Mood] + [质量 Quality] + +## 输出格式 (严格 JSON) +{ + "intent": "image_gen", + "confidence": 0.95, + "subIntent": "product_design", + "needsClarification": false, + "dimensions": { + "subject": "主体描述", + "action": "动作/姿态", + "style": "艺术风格", + "lighting": "光影效果", + "composition": "构图方式", + "color": "色彩方案", + "mood": "情绪氛围", + "quality": "质量关键词" + }, + "optimizedPrompt": "完整优化后的中文提示词(100-200字)", + "negativePrompt": "需要避免的元素(如:模糊、低质量、变形等)", + "suggestedModel": "alibaba-image", + "clarifyingQuestions": [] +} + +## 优化原则 +1. 保持用户原始意图不变 +2. 补充缺失的专业描述(光影、构图、氛围等) +3. 添加适当的质量关键词(高清、细节丰富、专业级等) +4. 使用中文输出 +5. 提示词长度控制在 100-200 字 +6. 对于 chat/vision 意图,optimizedPrompt 保持用户原始输入即可 + +## 特殊场景处理(图片编辑优先) + +1. **用户上传了图片 + 编辑类关键词** → image_edit(最高优先级) +2. **用户上传了图片 + 无明确意图** → 返回澄清问题,询问需要什么编辑 +3. **用户上传了图片 + 理解类关键词** → vision(千问3 VL) +4. **用户上传了图片 + 生成视频关键词** → video_gen(火山视频) +5. **用户无图片 + 生成类关键词** → image_gen(灵魂4.5) +6. **用户无图片 + 编辑类关键词** → needsClarification: true,提示"请上传图片" + +## 澄清问题示例 +当意图不明确时,返回以下澄清问题: +- "您想对这张图片做什么处理?(抠图/换背景/变清晰/其他)" +- "请描述您希望达到的效果" +- "需要我帮您去除背景吗?还是有其他编辑需求?"`; + +export interface SmartAnalysisResult { + intent: "image_gen" | "image_edit" | "video_gen" | "vision" | "chat"; + confidence: number; + subIntent?: string; + needsClarification: boolean; + dimensions: { + subject: string; + action: string; + style: string; + lighting: string; + composition: string; + color: string; + mood: string; + quality: string; + }; + optimizedPrompt: string; + negativePrompt?: string; + suggestedModel: string; + clarifyingQuestions?: string[]; +} + +export async function analyzeAndOptimize( + userInput: string, + hasImage: boolean, + chatHistory?: { role: string; content: string }[] +): Promise { + const contextInfo = hasImage ? "(用户上传了图片)" : ""; + + const { text } = await generateText({ + model: qwen("qwen3-turbo"), + system: ANALYZER_SYSTEM_PROMPT, + messages: [ + ...(chatHistory || []), + { + role: "user", + content: `${contextInfo}\n用户输入: ${userInput}` + } + ], + }); + + try { + return JSON.parse(text); + } catch (error) { + // 解析失败时返回默认值 + console.error("[SmartAnalyzer] JSON parse error:", error); + return { + intent: hasImage ? "vision" : "chat", + confidence: 0.5, + needsClarification: false, + dimensions: { + subject: userInput, + action: "", + style: "", + lighting: "", + composition: "", + color: "", + mood: "", + quality: "", + }, + optimizedPrompt: userInput, + suggestedModel: "qwen-vl", + }; + } +} +``` + +#### 3.1.2 模型路由器 (`lib/ai/model-router.ts`) + +```typescript +import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; + +interface ModelWithProvider { + model: { + id: string; + displayName: string; + modelId: string; + supportsImageGen: boolean; + supportsVision: boolean; + isDefault: boolean; + }; + provider: { + type: string; // alibaba, gemini, volcano-vision, volcano-video, alibaba-image, etc. + }; +} + +/** + * 基于当前系统已配置的模型,智能路由映射 + * + * 当前模型清单: + * - 千问3 (alibaba): 对话模型 + * - 既梦4.5 (volcano-vision): 图片生成 + * - GTP1.5 (gemini): 视觉理解 + * - 香蕉PRO (gemini): 视觉+图片生成 + * - 灵魂4.5 (alibaba-image): 视觉+图片生成+提示词扩展 + * - VIDEO/Seedance* (volcano-video): 视频生成 + */ +const INTENT_PROVIDER_MAP: Record = { + // 图片生成:优先选择 alibaba-image (灵魂4.5,支持提示词扩展) + "image_gen": { + providers: ["alibaba-image", "gemini", "volcano-vision"], + requireImageGen: true + }, + // 图片编辑:需要视觉能力 + 图片生成 + "image_edit": { + providers: ["alibaba-image", "gemini"], + requireVision: true, + requireImageGen: true + }, + // 视频生成:火山视频模型 + "video_gen": { + providers: ["volcano-video", "qianwen-video"] + }, + // 视觉理解:优先千问3 VL(成本低、效果好),然后是 gemini + "vision": { + providers: ["alibaba", "gemini", "alibaba-image"], + requireVision: true + }, + // 普通对话:阿里云千问3 VL(也支持视觉) + "chat": { + providers: ["alibaba", "openai", "local"] + }, +}; + +// 特殊模型 ID 映射(用于精确匹配) +const SPECIAL_MODEL_ROUTING: Record = { + // 图生视频场景:优先使用 SeedanceLiteI2V + "video_gen_with_image": "doubao-seedance-1-0-lite-i2v-250428", + // 纯文生视频场景:使用 SeedanceLiteT2V(成本低) + "video_gen_text_only": "doubao-seedance-1-0-lite-t2v-250428", + // 高质量视频:使用 SeedancePro + "video_gen_high_quality": "doubao-seedance-1-0-pro-250528", + // 快速视频:使用 SeedanceProFast + "video_gen_fast": "doubao-seedance-1-0-pro-fast-251015", +}; + +export async function routeToOptimalModel( + analysis: { + intent: string; + subIntent?: string; + suggestedModel?: string; + }, + hasImage: boolean = false, + availableModels?: ModelWithProvider[] +): Promise { + const models = availableModels || await getEnabledAiModelsWithProvider(); + + // 1. 特殊场景精确路由 + if (analysis.intent === "video_gen") { + if (hasImage) { + const i2vModel = models.find(m => m.model.modelId === SPECIAL_MODEL_ROUTING["video_gen_with_image"]); + if (i2vModel) { + console.log("[ModelRouter] 🎬 图生视频 → SeedanceLiteI2V"); + return i2vModel.model.id; + } + } else { + // 文生视频使用轻量版(成本低) + const t2vModel = models.find(m => m.model.modelId === SPECIAL_MODEL_ROUTING["video_gen_text_only"]); + if (t2vModel) { + console.log("[ModelRouter] 🎬 文生视频 → SeedanceLiteT2V"); + return t2vModel.model.id; + } + } + } + + // 2. 获取意图对应的路由规则 + const routingRule = INTENT_PROVIDER_MAP[analysis.intent] || INTENT_PROVIDER_MAP["chat"]; + + // 3. 多因素评分算法 + const scoredModels = models.map(({ model, provider }) => { + let score = 0; + + // 3.1 提供商类型匹配 (最高 50 分) + const providerIndex = routingRule.providers.indexOf(provider.type); + if (providerIndex !== -1) { + score += 50 - providerIndex * 10; // 越靠前分数越高 + } + + // 3.2 能力匹配 (最高 30 分) + if (routingRule.requireVision && model.supportsVision) { + score += 20; + } + if (routingRule.requireImageGen && model.supportsImageGen) { + score += 20; + } + + // 3.3 默认模型加分 (10 分) + if (model.isDefault) { + score += 10; + } + + // 3.4 特殊加分:alibaba-image 支持提示词扩展 + if (analysis.intent === "image_gen" && provider.type === "alibaba-image") { + score += 15; // 因为支持 supportsPromptExtend + } + + return { model, provider, score }; + }); + + // 4. 过滤掉不满足必要条件的模型 + const filteredModels = scoredModels.filter(({ model }) => { + if (routingRule.requireVision && !model.supportsVision) return false; + if (routingRule.requireImageGen && !model.supportsImageGen) return false; + return true; + }); + + // 5. 按分数排序,返回最高分模型 + const sortedModels = (filteredModels.length > 0 ? filteredModels : scoredModels) + .sort((a, b) => b.score - a.score); + + console.log("[ModelRouter] Scores:", sortedModels.slice(0, 5).map(s => + `${s.model.displayName}(${s.provider.type}): ${s.score}` + ).join(", ")); + + const selectedModel = sortedModels[0]?.model; + console.log(`[ModelRouter] ✅ Selected: ${selectedModel?.displayName} (${selectedModel?.id})`); + + return selectedModel?.id || models[0]?.model.id; +} +``` + +#### 3.1.3 修改 Chat API (`app/(chat)/api/chat/route.ts`) + +```typescript +// 在 Auto Mode Logic 部分替换为: + +import { analyzeAndOptimize } from "@/lib/ai/smart-analyzer"; +import { routeToOptimalModel } from "@/lib/ai/model-router"; + +// ========== Smart Auto Mode Logic ========== +if (finalModelId === "auto") { + console.log("[Smart Auto Mode] Starting intelligent analysis..."); + + // 获取用户最后一条消息 + const lastUserMessage = messages.findLast((m) => m.role === "user"); + if (!lastUserMessage) { + return new ChatSDKError("bad_request:api", "No user message found").toResponse(); + } + + // 提取文本和图片信息 + const textContent = lastUserMessage.parts + .filter((p) => p.type === "text") + .map((p) => p.text) + .join(" "); + const hasImage = lastUserMessage.parts.some( + (p) => p.type === "file" || p.type === "image" || p.type === "image_url" + ); + + // 1. 调用 Qwen3 进行智能分析 + const analysis = await analyzeAndOptimize(textContent, hasImage); + console.log("[Smart Auto Mode] Analysis result:", analysis); + + // 2. 智能模型路由 + const allModels = await getEnabledAiModelsWithProvider(); + finalModelId = await routeToOptimalModel(analysis, allModels); + console.log(`[Smart Auto Mode] ✅ Selected model: ${finalModelId}`); + + // 3. 如果是图片生成意图,使用优化后的提示词 + if (analysis.intent === "image_gen" && analysis.optimizedPrompt) { + console.log("[Smart Auto Mode] Using optimized prompt:", analysis.optimizedPrompt); + // 替换用户消息中的文本为优化后的提示词 + // TODO: 实现提示词替换逻辑 + } +} +// ========== End Smart Auto Mode Logic ========== +``` + +--- + +### Phase 2: 提示词替换与展示 + +**目标:** 将优化后的提示词应用到生成流程,并向用户展示优化过程 + +**修改:** +1. 在消息流中插入"提示词优化"提示 +2. 显示原始提示词 vs 优化后提示词 +3. 用户可以选择使用原始或优化版本 + +--- + +### Phase 3: 用户偏好学习 + +**目标:** 基于用户反馈学习偏好,提升满意度 + +**新增数据库表:** +```sql +CREATE TABLE user_preferences ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id), + preference_type VARCHAR(50) NOT NULL, -- style, color, quality, etc. + preference_value TEXT NOT NULL, + weight DECIMAL(3,2) DEFAULT 1.0, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +CREATE TABLE generation_feedback ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id), + message_id UUID NOT NULL, + original_prompt TEXT NOT NULL, + optimized_prompt TEXT, + model_used VARCHAR(100), + feedback_type VARCHAR(20), -- positive, negative, regenerate + feedback_text TEXT, + created_at TIMESTAMP DEFAULT NOW() +); +``` + +--- + +### Phase 4: 多轮对话细化 + +**目标:** 支持"更亮一点"、"换个风格"等模糊指令 + +**实现思路:** +1. 检测是否是对上一次生成的修改请求 +2. 解析修改意图(颜色/构图/风格/光影等) +3. 基于上下文生成新的优化提示词 +4. 保持主体不变,只调整指定维度 + +--- + +### Phase 5: 上下文记忆 + +**目标:** 跨会话保持风格一致性 + +**实现思路:** +1. 提取用户常用的风格/色彩/质量偏好 +2. 在新会话中自动应用历史偏好 +3. 支持用户主动保存"风格预设" + +--- + +## 四、API 设计 + +### 4.1 智能分析 API + +**Endpoint:** `POST /api/smart-analyze` + +**Request:** +```json +{ + "userInput": "帮我画一只可爱的猫咪", + "hasImage": false, + "chatHistory": [ + { "role": "user", "content": "你好" }, + { "role": "assistant", "content": "你好!有什么可以帮助你的?" } + ] +} +``` + +**Response:** +```json +{ + "intent": "image_gen", + "confidence": 0.95, + "dimensions": { + "subject": "一只可爱的猫咪,毛茸茸的橘色小猫", + "action": "蜷缩着身体,眼睛半眯", + "style": "写实摄影风格,柔焦效果", + "lighting": "温暖的自然光,侧光照明", + "composition": "近景特写,浅景深", + "color": "暖色调,橘色和米白色为主", + "mood": "温馨、慵懒、治愈", + "quality": "8K高清,细腻毛发质感,专业宠物摄影" + }, + "optimizedPrompt": "一只可爱的橘色小猫咪,毛茸茸的,蜷缩着身体眼睛半眯,写实摄影风格配合柔焦效果,温暖的自然侧光照明,近景特写浅景深构图,暖色调以橘色和米白色为主,营造温馨慵懒治愈的氛围,8K高清画质,细腻毛发质感,专业宠物摄影品质", + "negativePrompt": "模糊,低质量,变形,多余的肢体", + "suggestedModel": "alibaba-image" +} +``` + +--- + +## 五、配置项 + +### 5.1 环境变量 + +```env +# Qwen3 API 配置 (用于智能分析) +QWEN_API_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 +QWEN_API_KEY=your-qwen-api-key + +# 智能分析功能开关 +SMART_AUTO_ENABLED=true + +# 提示词优化最大长度 +PROMPT_OPTIMIZATION_MAX_LENGTH=200 +``` + +### 5.2 管理后台配置 + +在"网站设置"中新增: + +| 配置项 | 类型 | 默认值 | 说明 | +|-------|------|--------|------| +| enableSmartAuto | boolean | true | 是否启用智能自动模式 | +| showPromptOptimization | boolean | true | 是否向用户展示优化过程 | +| allowUserOverride | boolean | true | 是否允许用户使用原始提示词 | +| optimizationModel | string | qwen3-turbo | 用于分析的模型 | + +--- + +## 六、性能与成本考虑 + +### 6.1 延迟优化 + +| 阶段 | 预估延迟 | 优化策略 | +|-----|---------|---------| +| Qwen3 分析 | 500-1000ms | 使用 qwen3-turbo,流式响应 | +| 模型路由 | <50ms | 内存缓存模型列表 | +| 提示词优化 | 已包含在分析中 | - | +| 总额外延迟 | ~1s | 可接受范围 | + +### 6.2 成本估算 + +| 调用类型 | 单次成本 | 日均调用 | 日成本 | +|---------|---------|---------|--------| +| Qwen3-turbo | ¥0.001/1K tokens | 1000次 | ¥1-2 | +| 总月成本 | - | - | ¥30-60 | + +--- + +## 七、测试计划 + +### 7.1 单元测试 + +```typescript +// __tests__/smart-analyzer.test.ts + +describe("SmartAnalyzer", () => { + test("should detect image_gen intent", async () => { + const result = await analyzeAndOptimize("画一只猫", false); + expect(result.intent).toBe("image_gen"); + expect(result.confidence).toBeGreaterThan(0.8); + }); + + test("should detect image_edit intent with image", async () => { + const result = await analyzeAndOptimize("帮我去掉背景", true); + expect(result.intent).toBe("image_edit"); + }); + + test("should optimize prompt with all dimensions", async () => { + const result = await analyzeAndOptimize("画一只猫", false); + expect(result.dimensions.subject).toBeTruthy(); + expect(result.optimizedPrompt.length).toBeGreaterThan(50); + }); +}); +``` + +### 7.2 集成测试 + +1. 完整流程测试:用户输入 → 分析 → 路由 → 生成 +2. 各种意图类型覆盖测试 +3. 边界情况测试(空输入、超长输入、乱码等) + +--- + +## 八、里程碑 + +| 阶段 | 内容 | 预计时间 | 交付物 | +|-----|------|---------|--------| +| Phase 1 | 核心功能 MVP | 2-3 天 | 智能分析 + 模型路由 | +| Phase 2 | 提示词展示 | 1 天 | UI 优化展示 | +| Phase 3 | 偏好学习 | 2-3 天 | 数据库 + 学习算法 | +| Phase 4 | 多轮细化 | 2 天 | 对话细化功能 | +| Phase 5 | 上下文记忆 | 2 天 | 跨会话一致性 | +| **总计** | | **9-11 天** | | + +--- + +## 九、风险与应对 + +| 风险 | 影响 | 应对措施 | +|-----|------|---------| +| Qwen API 不稳定 | 功能不可用 | 降级到规则匹配 | +| 分析结果不准确 | 用户体验差 | 允许用户覆盖 | +| 提示词优化过度 | 偏离用户意图 | 保留原始提示词选项 | +| 成本超预算 | 财务压力 | 设置调用频率限制 | + +--- + +## 十、参考资料 + +### 核心参考 + +1. [Lovart.ai 官方文档](https://www.lovart.ai/features) - 世界首个 AI 设计智能体平台 +2. [LLMRouter 开源库](https://github.com/ulab-uiuc/LLMRouter) - 16+ 种路由算法,支持 KNN/SVM/MLP/BERT 等 +3. [Qwen-Agent 官方文档](https://qwenlm.github.io/Qwen-Agent/en/guide/) - 千问代理框架,内置 `image_gen` 工具 +4. [Maestro: Self-Improving T2I Generation](https://arxiv.org/html/2509.10704v1) - Google 自进化图像生成系统 +5. [PromptSculptor: Multi-Agent Prompt Optimization](https://arxiv.org/html/2509.12446v1) - EMNLP 2025 多代理提示词优化 + +### 路由算法 + +6. [Router-R1](https://ulab-uiuc.github.io/Router-R1/) - NeurIPS 2025,强化学习多轮路由 + - 支持 "think" + "route" 交替决策 + - 成本-性能权衡优化 + - 零样本泛化到新模型 + +### 提示词优化 + +7. [PromptEnhancer (腾讯混元)](https://hunyuan-promptenhancer.github.io/) - Chain-of-Thought 提示词重写 + - 开源代码: [GitHub](https://github.com/Hunyuan-PromptEnhancer/PromptEnhancer) + - 基于 24 个关键点的 AlignEvaluator 奖励模型 + - 解决属性绑定、否定、组合关系等问题 + +8. [Stable Diffusion 3.5 Prompt Guide](https://stability.ai/learning-hub/stable-diffusion-3-5-prompt-guide) - 官方提示词指南 + +### 最佳实践 + +9. [提示词公式](https://uchaaaa.medium.com/the-most-effective-way-to-prompt-the-best-designs-on-midjourney-d6c63e9a3f06): + ``` + [Medium] + [Style/Composition] + [Subject] + [Action] + [Scene] + [Lighting] + [Color] + ``` + +10. [Qwen-Agent 工具调用](https://github.com/QwenLM/Qwen-Agent/blob/main/docs/tool.md) - 内置工具和自定义工具注册 + +--- + +## 附录 A: 提示词优化示例 + +### 示例 1: 简单描述 + +**用户输入:** "画一只猫" + +**分析结果:** +```json +{ + "intent": "image_gen", + "confidence": 0.98, + "dimensions": { + "subject": "一只可爱的猫咪", + "action": "安静地坐着", + "style": "写实摄影风格", + "lighting": "柔和的自然光", + "composition": "中景构图", + "color": "自然色调", + "mood": "温馨平和", + "quality": "高清,细节丰富" + }, + "optimizedPrompt": "一只可爱的猫咪,毛发柔顺光亮,安静地坐着凝视镜头,写实摄影风格,柔和的自然光照明,中景构图突出主体,自然和谐的色调,营造温馨平和的氛围,高清画质,毛发细节丰富,专业宠物摄影" +} +``` + +### 示例 2: 产品设计 + +**用户输入:** "设计一个简约风格的台灯" + +**分析结果:** +```json +{ + "intent": "image_gen", + "confidence": 0.95, + "subIntent": "product_design", + "dimensions": { + "subject": "一盏简约风格的现代台灯", + "action": "静置展示", + "style": "北欧极简工业设计风格", + "lighting": "产品摄影棚灯光,柔和均匀", + "composition": "45度角产品展示图", + "color": "白色/木色/黑色", + "mood": "简洁高端现代", + "quality": "产品级渲染,材质真实" + }, + "optimizedPrompt": "一盏简约现代风格的台灯产品设计图,北欧极简工业设计语言,圆润流畅的造型线条,白色灯罩搭配原木底座,产品摄影棚专业灯光布置,45度角展示产品全貌,简洁高端的现代气质,产品级3D渲染品质,材质纹理真实细腻,适合电商展示" +} +``` + +--- + +## 附录 B: 从参考资料中提取的关键技术 + +### B.1 PromptSculptor 四代理架构 + +来源: EMNLP 2025 + +PromptSculptor 将提示词优化分解为 **4 个专业化代理**: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ PromptSculptor 架构 │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ 用户模糊提示 ──▶ Agent 1: 意图推断 ──▶ Agent 2: 场景丰富 │ +│ │ │ │ +│ ▼ ▼ │ +│ 推断隐含语境 补充背景细节 │ +│ (Chain-of-Thought) │ +│ │ │ │ +│ └──────────┬───────────┘ │ +│ ▼ │ +│ Agent 3: 自我评估 ──▶ Agent 4: 反馈调优 │ +│ │ │ │ +│ ▼ ▼ │ +│ 与原始意图对齐 用户反馈迭代 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +**可借鉴点:** +- Chain-of-Thought 推理隐含语境 +- 自我评估确保不偏离用户意图 +- 支持用户反馈迭代 + +### B.2 Maestro 自进化系统 + +来源: Google Research + +Maestro 使用 **自我批评 + 自我进化** 机制: + +| 组件 | 功能 | 实现方式 | +|-----|------|---------| +| Critic Agents | 识别图像弱点 | MLLM 专业化评估 | +| Verifier Agent | 整合编辑信号 | 保持用户意图 | +| MLLM-as-a-Judge | 头对头比较 | 选择更好的版本 | +| Prompt Evolution | 迭代优化提示词 | 丢弃问题输出 | + +**可借鉴点:** +- 多个 MLLM Agent 协作评估 +- 生成多个版本进行比较 +- 保持用户意图的验证机制 + +### B.3 Router-R1 强化学习路由 + +来源: NeurIPS 2025 + +Router-R1 创新点: + +1. **顺序决策过程**: 路由不是一次性的,而是多轮交互 +2. **Think + Route 交替**: + - `think`: 内部推理,分析任务 + - `route`: 选择模型,获取响应 +3. **成本奖励**: 在 RL 训练中加入成本惩罚,平衡性能和花费 +4. **零样本泛化**: 仅需模型描述(定价、延迟、示例性能)即可集成新模型 + +**可借鉴点:** +- 可以在我们的系统中加入成本感知路由 +- 支持动态添加新模型而无需重新训练 + +### B.4 PromptEnhancer 24 关键点 + +来源: 腾讯混元 + +PromptEnhancer 基于 **24 个常见 T2I 失败模式** 训练奖励模型: + +| 类别 | 关键点示例 | +|-----|----------| +| 属性绑定 | 颜色/材质是否正确附加到对象 | +| 对象计数 | 数量是否准确 | +| 空间关系 | 左右/上下/前后位置是否正确 | +| 否定处理 | "没有XX" 是否被正确理解 | +| 风格一致性 | 整体风格是否统一 | +| 细节完整性 | 重要元素是否缺失 | + +**可借鉴点:** +- 可以用这些关键点来评估生成质量 +- 反馈循环中使用这些标准 + +### B.5 Qwen-Agent 内置工具 + +来源: Qwen-Agent 官方文档 + +Qwen-Agent 已内置以下工具: + +| 工具名 | 功能 | +|-------|------| +| `image_gen` | 图片生成 | +| `code_interpreter` | 执行 Python 代码 | +| `web_search` | 网页搜索 | +| `web_extractor` | 网页内容提取 | +| `image_search` | 图片搜索 | +| `image_zoom_in_tool` | 图片局部放大 | + +**可借鉴点:** +- 可以直接使用 Qwen-Agent 框架实现工具调用 +- 支持 MCP (Model Context Protocol) 集成外部工具 + +### B.6 LLMRouter 16+ 路由算法 + +来源: LLMRouter 开源库 + +可选的路由算法: + +| 类型 | 算法 | 特点 | +|-----|------|------| +| 基础 | KNN, SVM, MLP | 快速,适合简单场景 | +| 进阶 | Matrix Factorization, Elo Rating | 考虑模型能力差异 | +| 深度 | BERT-based, CausalLM | 理解语义,更准确 | +| 多轮 | Router-R1, KNN Multi-Round | 支持复杂任务 | +| 个性化 | GMT Router | 学习用户偏好 | + +**可借鉴点:** +- 初期可以使用 KNN/MLP 快速实现 +- 后期可以升级到 BERT-based 或个性化路由 + +--- + +## 附录 C: 图片编辑提示词模板库(核心) + +### C.1 抠图/去背景模板 + +``` +# 基础抠图 +去除图片背景,保留主体{subject}, +输出透明背景PNG格式, +边缘处理:平滑自然,保留细节(如发丝、毛发) + +# 产品抠图 +精准抠出产品主体, +保留产品阴影和反光效果, +边缘清晰锐利,无毛边 + +# 人物抠图 +保留人物完整轮廓, +特别注意发丝和衣服边缘的细节处理, +皮肤边缘自然过渡 +``` + +### C.2 换背景模板 + +``` +# 纯色背景 +将背景替换为{color}纯色背景, +保持主体阴影自然, +光影与主体协调一致 + +# 场景背景 +将背景替换为{scene}场景, +场景风格:{style}, +光照方向与主体一致, +透视关系自然合理 + +# 渐变背景 +背景设为从{color1}到{color2}的渐变, +渐变方向:{direction}, +主体与背景融合自然 +``` + +### C.3 图片增强模板 + +``` +# 通用增强 +提升图片整体清晰度和质量, +保持自然色彩,不过度锐化, +去除噪点,优化细节 + +# 产品图增强 +增强产品细节和材质表现, +优化光影效果, +提升质感和专业度 + +# 人像增强 +优化面部细节,保持自然肤色, +增强眼神光, +适度美化但不失真 +``` + +### C.4 图像拓展 (Outpainting) 模板 + +``` +# 方向扩展 +向{direction}方向扩展图片{percentage}%, +保持原有风格和色调一致, +光影过渡自然,无明显接缝 + +# 全方向扩展 +等比例扩展画布至{ratio}尺寸, +扩展区域内容与原图风格协调, +保持透视和景深一致性 +``` + +### C.5 局部修改 (Inpainting) 模板 + +``` +# 去除对象 +去除图片中的{object}, +用周围环境自然填充, +保持整体风格一致 + +# 替换对象 +将图片中的{old_object}替换为{new_object}, +新对象风格与画面协调, +光影和透视关系正确 + +# 修复瑕疵 +修复图片中的{defect}(如水印/污点/破损), +自然填充,看不出修复痕迹 +``` + +### C.6 风格迁移模板 + +``` +# 艺术风格 +将照片转换为{style}艺术风格, +保持主体可识别性, +色彩风格:{color_style} + +# 动漫/卡通风格 +转换为{anime_style}动漫风格, +保留人物特征和表情, +线条清晰,色彩鲜明 +``` + +### C.7 图片生成模板(辅助) + +``` +# 通用生成 +[主体] {subject},[动作] {action}, +[风格] {style}风格, +[光影] {lighting}, +[构图] {composition}, +[色彩] {color}色调, +[氛围] {mood}氛围, +[质量] 高清,细节丰富 + +# 产品图生成 +产品:{product_name}, +展示角度:{angle}, +背景:{background}, +灯光:产品摄影棚专业布光, +质量:产品级渲染,材质真实 +``` + +### C.8 负面提示词模板 + +``` +# 通用负面 +模糊,低质量,变形,水印,噪点, +过曝,欠曝,不自然的颜色,比例失调 + +# 人物负面 +多余肢体,变形的脸,不对称, +不自然的表情,僵硬的姿势 + +# 产品负面 +材质失真,光影错误,比例错误, +背景杂乱,细节丢失 +``` + +--- + +*文档结束* diff --git a/lib/ai/model-router.ts b/lib/ai/model-router.ts new file mode 100644 index 000000000..4ccd8625a --- /dev/null +++ b/lib/ai/model-router.ts @@ -0,0 +1,231 @@ +/** + * 智能模型路由器 + * 根据用户意图选择最佳AI模型 + * + * 核心逻辑:图片编辑场景优先使用 alibaba-image (灵魂4.5) + */ + +import { getEnabledAiModelsWithProvider } from "@/lib/db/queries"; + +// 路由结果类型 +export interface RouteResult { + id: string; + displayName: string; + providerType: string; + modelId: string; + reason: string; +} + +// 意图到模型的映射配置 +// providerTypes 按优先级排序,第一个是首选 +const INTENT_MODEL_MAP: Record< + string, + { + providerTypes: string[]; + requireVision?: boolean; + requireImageGen?: boolean; + description: string; + } +> = { + // 图片编辑:优先 alibaba-image(灵魂4.5,支持提示词扩展) + image_edit: { + providerTypes: ["alibaba-image", "gemini"], + requireVision: true, + requireImageGen: true, + description: "图片编辑", + }, + + // 视觉理解:优先千问3 VL(成本低效果好) + vision: { + providerTypes: ["alibaba", "gemini"], + requireVision: true, + description: "图片理解", + }, + + // 图片生成:优先灵魂4.5 + image_gen: { + providerTypes: ["alibaba-image", "gemini", "volcano-vision"], + requireImageGen: true, + description: "图片生成", + }, + + // 视频生成 + video_gen: { + providerTypes: ["volcano-video", "qianwen-video"], + description: "视频生成", + }, + + // 普通对话:优先千问3 + chat: { + providerTypes: ["alibaba", "openai", "local"], + description: "对话", + }, +}; + +// 子意图的特殊路由配置(覆盖默认配置) +const SUB_INTENT_OVERRIDES: Record< + string, + { + providerTypes?: string[]; + reason?: string; + } +> = { + // 抠图:alibaba-image 效果最好 + remove_background: { + providerTypes: ["alibaba-image", "gemini"], + reason: "抠图首选灵魂4.5", + }, + + // 换背景:alibaba-image 支持场景生成 + replace_background: { + providerTypes: ["alibaba-image", "gemini"], + reason: "换背景首选灵魂4.5", + }, + + // 图片增强 + enhance: { + providerTypes: ["alibaba-image", "gemini", "volcano-vision"], + reason: "增强首选灵魂4.5", + }, + + // 风格迁移:gemini 可能更有创意 + style_transfer: { + providerTypes: ["gemini", "alibaba-image"], + reason: "风格迁移优选Gemini", + }, +}; + +/** + * 路由到最佳模型 + */ +export async function routeToModel(params: { + intent: string; + subIntent?: string; + hasImage: boolean; +}): Promise { + const { intent, subIntent, hasImage } = params; + + console.log("[Model Router] Routing:", { intent, subIntent, hasImage }); + + // 获取所有可用模型 + const allModels = await getEnabledAiModelsWithProvider(); + console.log("[Model Router] Available models:", allModels.length); + + // 获取意图对应的配置 + let config = INTENT_MODEL_MAP[intent] || INTENT_MODEL_MAP["chat"]; + + // 检查是否有子意图的特殊配置 + if (subIntent && SUB_INTENT_OVERRIDES[subIntent]) { + const override = SUB_INTENT_OVERRIDES[subIntent]; + if (override.providerTypes) { + config = { ...config, providerTypes: override.providerTypes }; + } + } + + // 按优先级查找匹配的模型 + 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, + modelId: selected.model.modelId, + reason: subIntent + ? `${config.description}/${subIntent} → ${selected.model.displayName}` + : `${config.description} → ${selected.model.displayName}`, + }; + + console.log("[Model Router] ✅ Selected:", result); + return result; + } + } + + // 兜底逻辑:返回任意可用的图片编辑模型 + const fallbackCandidates = allModels.filter( + (m) => + !m.model.isSubModel && + m.model.isEnabled && + (m.model.supportsImageGen || m.model.supportsVision) + ); + + if (fallbackCandidates.length > 0) { + const fallback = fallbackCandidates[0]; + console.log("[Model Router] Using fallback (with image capability):", fallback.model.displayName); + return { + id: fallback.model.id, + displayName: fallback.model.displayName, + providerType: fallback.provider.type, + modelId: fallback.model.modelId, + reason: `fallback (${config.description})`, + }; + } + + // 最终兜底:返回任意可用模型 + const anyModel = allModels.find((m) => !m.model.isSubModel && m.model.isEnabled); + if (anyModel) { + console.log("[Model Router] Using any available model:", anyModel.model.displayName); + return { + id: anyModel.model.id, + displayName: anyModel.model.displayName, + providerType: anyModel.provider.type, + modelId: anyModel.model.modelId, + reason: "fallback (any)", + }; + } + + // 如果没有任何模型,抛出错误 + throw new Error("No available models for routing"); +} + +/** + * 获取意图的推荐模型列表(用于 UI 展示) + */ +export function getRecommendedModelsForIntent(intent: string): string[] { + const config = INTENT_MODEL_MAP[intent]; + return config ? config.providerTypes : INTENT_MODEL_MAP["chat"].providerTypes; +} + +/** + * 检查模型是否适合指定意图 + */ +export function isModelSuitableForIntent( + providerType: string, + intent: string, + supportsVision: boolean, + supportsImageGen: boolean +): boolean { + const config = INTENT_MODEL_MAP[intent]; + if (!config) return true; // 未知意图,允许任何模型 + + // 检查 provider 类型是否匹配 + if (!config.providerTypes.includes(providerType)) { + return false; + } + + // 检查能力要求 + if (config.requireVision && !supportsVision) return false; + if (config.requireImageGen && !supportsImageGen) return false; + + return true; +} diff --git a/lib/ai/prompt-optimizer.ts b/lib/ai/prompt-optimizer.ts new file mode 100644 index 000000000..abe837014 --- /dev/null +++ b/lib/ai/prompt-optimizer.ts @@ -0,0 +1,231 @@ +/** + * 提示词优化器 + * 将用户简单输入转换为专业的图片编辑提示词 + * + * 主要应用场景:图片编辑(抠图、换背景、增强等) + */ + +// 优化结果类型 +export interface OptimizeResult { + originalPrompt: string; + optimizedPrompt: string; + negativePrompt: string; +} + +// 图片编辑子意图的提示词模板 +const EDIT_TEMPLATES: Record< + string, + { + template: string; + negative: string; + extractors: Record; + defaults: Record; + } +> = { + remove_background: { + template: + "精准抠图:去除图片背景,保留主体完整清晰,输出透明背景PNG格式。边缘处理要求:平滑自然无锯齿,保留精细细节(如发丝、毛发、边缘纹理)。主体保持原有清晰度和色彩。", + negative: "残留背景色块,边缘毛糙,锯齿明显,主体不完整,边缘模糊,细节丢失,颜色溢出", + extractors: {}, + defaults: {}, + }, + + replace_background: { + template: + "背景替换:将图片背景替换为{background}。要求:保持主体完整清晰不变形,边缘过渡自然平滑,光影效果与新背景协调一致。{extra}", + negative: "残留原背景,边缘不自然,透视错误,主体变形,光影不协调,明显P图痕迹,边缘光晕", + extractors: { + background: /(?:换成|改成|替换为|变成|换为|改为)(.+?)(?:背景|底|$)/, + }, + defaults: { + background: "纯白色(#FFFFFF)", + extra: "保留主体自然阴影效果", + }, + }, + + enhance: { + template: + "图片增强:提升图片整体清晰度和画质。要求:保持自然色彩不失真,智能去除噪点,增强细节层次,适度锐化边缘。{extra}", + negative: "过度锐化,色彩失真,噪点增加,伪影,画质下降,不自然的对比度,颜色过饱和", + extractors: {}, + defaults: { + extra: "整体效果自然真实", + }, + }, + + extend: { + template: + "图像拓展(Outpainting):向{direction}方向扩展图片约{amount}。要求:扩展区域的内容、风格、色调与原图保持高度一致,光影过渡自然流畅,无明显接缝痕迹,透视关系正确。", + negative: "风格不一致,明显接缝,透视错误,内容突变,色调不匹配,光影断裂", + extractors: { + direction: /向?(上|下|左|右|四周|周围)/, + amount: /(\d+%?|一倍|两倍|50%|100%)/, + }, + defaults: { + direction: "四周", + amount: "50%", + }, + }, + + inpaint: { + template: + "局部修改(Inpainting):{action}图片中的{target}。要求:使用周围环境自然填充修改区域,保持整体风格、色调、光影一致,无任何修复痕迹,过渡自然。", + negative: "明显修复痕迹,风格不一致,内容错误,边缘不自然,色差明显,纹理断裂", + extractors: { + target: /(?:去除|消除|擦掉|删除|移除|P掉|p掉)(.+?)(?:,|。|$| )/, + action: /(去除|消除|擦掉|删除|移除|修改)/, + }, + defaults: { + target: "指定区域内的元素", + action: "去除", + }, + }, + + style_transfer: { + template: + "风格迁移:将图片转换为{style}风格。要求:保持主体可识别性和基本特征,色彩风格协调统一,整体效果自然美观。", + negative: "主体变形严重,特征丢失,风格不统一,色彩异常,人物不可识别", + extractors: { + style: /(?:转换为|变成|改成|转成)(.+?)(?:风格|$)/, + }, + defaults: { + style: "卡通动漫", + }, + }, + + resize: { + template: + "尺寸调整:将图片{action}至{size}。要求:保持画质清晰,比例协调,细节不丢失。", + negative: "画质损失严重,比例失调,模糊,变形", + extractors: { + size: /(\d+[x×]\d+|\d+%)/, + action: /(放大|缩小|调整|裁剪)/, + }, + defaults: { + size: "目标尺寸", + action: "调整", + }, + }, + + color_adjust: { + template: + "颜色调整:对图片进行{adjustment}处理。要求:保持自然效果,色彩协调,不过度调整。", + negative: "色彩失真,过度调整,不自然,偏色严重", + extractors: { + adjustment: /(?:调整|增加|减少|提高|降低)(.+?)(?:,|。|$| )/, + }, + defaults: { + adjustment: "色彩优化", + }, + }, +}; + +/** + * 优化提示词 + */ +export function optimizePrompt(params: { + originalPrompt: string; + intent: string; + subIntent?: string; +}): OptimizeResult { + const { originalPrompt, intent, subIntent } = params; + + console.log("[Prompt Optimizer] Input:", { originalPrompt, intent, subIntent }); + + // 只对图片编辑类意图进行优化 + if (intent !== "image_edit") { + return { + originalPrompt, + optimizedPrompt: originalPrompt, + negativePrompt: "模糊,低质量,变形,水印,失真", + }; + } + + // 如果没有子意图,返回通用优化 + if (!subIntent) { + return { + originalPrompt, + optimizedPrompt: `图片编辑:${originalPrompt}。要求:效果自然,画质清晰,细节完整。`, + negativePrompt: "模糊,低质量,变形,水印,失真,不自然", + }; + } + + const template = EDIT_TEMPLATES[subIntent]; + if (!template) { + console.log("[Prompt Optimizer] No template for subIntent:", subIntent); + return { + originalPrompt, + optimizedPrompt: originalPrompt, + negativePrompt: "模糊,低质量,变形,水印,失真", + }; + } + + // 使用模板生成优化后的提示词 + let optimizedPrompt = template.template; + + // 从用户输入中提取参数并填充模板 + for (const [key, regex] of Object.entries(template.extractors)) { + const match = originalPrompt.match(regex); + let value = match ? match[1].trim() : template.defaults[key] || ""; + + // 清理提取的值 + value = value.replace(/[,。!?,.!?]/g, "").trim(); + + if (!value) { + value = template.defaults[key] || ""; + } + + optimizedPrompt = optimizedPrompt.replace(`{${key}}`, value); + } + + // 填充剩余的默认值 + for (const [key, defaultValue] of Object.entries(template.defaults)) { + optimizedPrompt = optimizedPrompt.replace(`{${key}}`, defaultValue); + } + + // 附加用户原始意图(如果优化后的提示词没有完全覆盖用户需求) + if (originalPrompt.length > 10 && !optimizedPrompt.includes(originalPrompt)) { + optimizedPrompt = `${optimizedPrompt}\n\n用户补充要求:${originalPrompt}`; + } + + const result: OptimizeResult = { + originalPrompt, + optimizedPrompt, + negativePrompt: template.negative, + }; + + console.log("[Prompt Optimizer] Output:", result); + return result; +} + +/** + * 提取背景描述(辅助函数) + */ +export function extractBackgroundDescription(text: string): string { + // 尝试提取用户描述的背景 + const patterns = [ + /(?:换成|改成|替换为|变成|换为|改为)(.+?)(?:背景|底)/, + /(.+?)(?:背景|底)$/, + /背景(?:换成|改成|替换为|变成)(.+)/, + ]; + + for (const pattern of patterns) { + const match = text.match(pattern); + if (match && match[1]) { + return match[1].trim(); + } + } + + return "纯白色"; +} + +/** + * 检测是否需要保留阴影 + */ +export function shouldPreserveShadow(text: string): boolean { + // 产品图、商品图通常需要保留阴影 + if (/产品|商品|电商|白底|纯白/.test(text)) { + return true; + } + return false; +} diff --git a/lib/ai/smart-analyzer.ts b/lib/ai/smart-analyzer.ts new file mode 100644 index 000000000..f809c1589 --- /dev/null +++ b/lib/ai/smart-analyzer.ts @@ -0,0 +1,347 @@ +/** + * 智能意图分析器 + * 分析用户输入,识别图片编辑意图 + * + * 主要应用场景:图片编辑(抠图、换背景、增强等) + */ + +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 - 图片理解(需要用户上传了图片) +触发词:看、识别、分析、描述、这是什么、有什么、tell me、what is + +### 3. image_gen - 图片生成(不需要上传图片) +触发词:画、绘制、生成图片、创建、设计、画一个、生成一张 + +### 4. video_gen - 视频生成 +触发词:视频、动画、动起来、让它动 + +### 5. chat - 普通对话(默认) + +## 输出格式(严格JSON,不要有其他内容) +{ + "intent": "image_edit", + "subIntent": "replace_background", + "confidence": 0.95, + "needsClarification": false, + "clarifyingQuestions": [] +} + +## 特殊规则 +1. 如果用户上传了图片且有编辑类关键词 → image_edit +2. 如果用户上传了图片但意图不明确 → needsClarification: true,并提供澄清问题 +3. 如果用户要求编辑但没上传图片 → needsClarification: true,提示"请上传图片" +4. 只输出JSON,不要有任何解释文字`; + +/** + * 分析用户意图 + */ +export async function analyzeIntent(params: { + text: string; + hasImage: boolean; + imageUrls?: string[]; +}): Promise { + const { text, hasImage, imageUrls } = params; + + console.log("[Smart Analyzer] Analyzing intent:", { text, hasImage, imageCount: imageUrls?.length }); + + // 先尝试关键词快速匹配(高置信度场景直接返回,节省LLM调用) + const quickResult = quickKeywordMatch(text, hasImage); + if (quickResult.confidence >= 0.9) { + console.log("[Smart Analyzer] Quick match result:", quickResult); + return quickResult; + } + + // 尝试使用 Qwen3 VL 进行深度分析 + try { + const llmResult = await analyzWithLLM(text, hasImage); + if (llmResult) { + console.log("[Smart Analyzer] LLM analysis result:", llmResult); + return llmResult; + } + } catch (error) { + console.error("[Smart Analyzer] LLM analysis failed:", error); + } + + // 回退到完整关键词分析 + const fallbackResult = fallbackKeywordAnalysis(text, hasImage); + console.log("[Smart Analyzer] Fallback result:", fallbackResult); + return fallbackResult; +} + +/** + * 快速关键词匹配(高置信度场景) + */ +function quickKeywordMatch(text: string, hasImage: boolean): AnalysisResult { + const lowerText = text.toLowerCase(); + + if (hasImage) { + // 抠图/去背景 - 高频场景 + if (/抠图|去背景|透明背景|去背|扣图|移除背景/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "remove_background", + confidence: 0.95, + }; + } + + // 换背景 - 高频场景 + if (/换背景|白底|改背景|背景换成|纯色背景|白色背景/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "replace_background", + confidence: 0.95, + }; + } + + // 图片增强 - 高频场景 + if (/变清晰|高清|锐化|降噪|清晰一点|更清晰|提升质量/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "enhance", + confidence: 0.95, + }; + } + + // P图/去除某物 + if (/P掉|p掉|去除|消除|擦掉|删除.*(?:人|物|水印|logo)/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "inpaint", + confidence: 0.95, + }; + } + } + + // 视频生成 + if (/生成视频|做视频|视频生成|动起来|让.{0,3}动/.test(lowerText)) { + return { + intent: "video_gen", + confidence: 0.95, + }; + } + + // 返回低置信度结果,触发LLM分析 + return { + intent: "chat", + confidence: 0.3, + }; +} + +/** + * 使用 LLM 进行深度分析 + */ +async function analyzWithLLM(text: string, hasImage: boolean): Promise { + // 获取千问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"); + return null; + } + + const model = await getLanguageModelById(qwenModel.model.id); + if (!model) { + console.log("[Smart Analyzer] Failed to get language model"); + return null; + } + + // 构建用户消息 + const userMessage = hasImage + ? `用户上传了图片,请求内容:"${text}"` + : `用户请求(无图片):"${text}"`; + + console.log("[Smart Analyzer] Calling Qwen3 VL for analysis"); + + // 调用模型分析 + const { text: responseText } = await generateText({ + model, + system: ANALYZER_SYSTEM_PROMPT, + prompt: userMessage, + temperature: 0.1, + maxTokens: 300, + } as any); + + // 解析JSON响应 + const jsonMatch = responseText.match(/\{[\s\S]*\}/); + if (jsonMatch) { + try { + const result = JSON.parse(jsonMatch[0]) as AnalysisResult; + return result; + } catch (e) { + console.error("[Smart Analyzer] Failed to parse LLM response:", e); + } + } + + return null; +} + +/** + * 回退方案:完整关键词匹配 + */ +export 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 (/扩展|拓展|延伸|扩图|outpainting|拓宽|扩大/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "extend", + confidence: 0.9, + }; + } + + // 局部修改/去除 + if (/去除|消除|擦掉|P掉|p掉|删除|修改.*部分|移除.*(?:人|物|水印|logo|文字)/.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: "image_edit", + subIntent: "color_adjust", + confidence: 0.9, + }; + } + + // 尺寸调整 + if (/缩放|放大|缩小|调整尺寸|裁剪|resize|crop/.test(lowerText)) { + return { + intent: "image_edit", + subIntent: "resize", + confidence: 0.9, + }; + } + + // 通用编辑关键词 + if (/修图|P图|改图|调图|处理.*图|编辑.*图|优化.*图/.test(lowerText)) { + return { + intent: "image_edit", + confidence: 0.8, + needsClarification: true, + clarifyingQuestions: [ + "您想对这张图片做什么处理?(抠图/换背景/变清晰/其他)", + ], + }; + } + + // 视觉理解 + if (/看|识别|分析|描述|这是什么|有什么|tell me|what is|看看|帮我看/.test(lowerText)) { + return { intent: "vision", confidence: 0.85 }; + } + + // 有图但意图不明确 + return { + intent: "image_edit", + confidence: 0.5, + needsClarification: true, + clarifyingQuestions: [ + "您想对这张图片做什么处理?(抠图/换背景/变清晰/局部修改/其他)", + ], + }; + } + + // === 无图片场景 === + + // 图片生成 + if (/画|绘制|生成图|创建.*图|设计.*图|画一个|生成一张|做一张/.test(lowerText)) { + return { intent: "image_gen", confidence: 0.85 }; + } + + // 视频生成 + if (/视频|动画|动起来|生成视频|做视频|视频生成/.test(lowerText)) { + return { intent: "video_gen", confidence: 0.85 }; + } + + // 需要图片但没有上传 + if (/抠图|去背景|换背景|修图|P图|编辑图/.test(lowerText)) { + return { + intent: "image_edit", + confidence: 0.7, + needsClarification: true, + clarifyingQuestions: ["请先上传您要编辑的图片"], + }; + } + + // 默认对话 + return { intent: "chat", confidence: 0.7 }; +}