新增智能自动模式功能: - smart-analyzer.ts: 智能意图分析器,识别抠图/换背景/增强等8种子意图 - prompt-optimizer.ts: 提示词优化器,将简单输入转为专业提示词 - model-router.ts: 智能模型路由器,根据意图选择最佳模型 - 修改route.ts集成新模块,替换原有关键词匹配逻辑 Co-authored-by: Cursor <cursoragent@cursor.com>
348 lines
10 KiB
TypeScript
348 lines
10 KiB
TypeScript
/**
|
||
* 智能意图分析器
|
||
* 分析用户输入,识别图片编辑意图
|
||
*
|
||
* 主要应用场景:图片编辑(抠图、换背景、增强等)
|
||
*/
|
||
|
||
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<AnalysisResult> {
|
||
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<AnalysisResult | null> {
|
||
// 获取千问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 };
|
||
}
|