ai-chatbot/lib/ai/smart-analyzer.ts
Your Name 8763e8d53f
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: 智能图片编辑系统 - 意图分析、提示词优化、模型路由
新增智能自动模式功能:
- smart-analyzer.ts: 智能意图分析器,识别抠图/换背景/增强等8种子意图
- prompt-optimizer.ts: 提示词优化器,将简单输入转为专业提示词
- model-router.ts: 智能模型路由器,根据意图选择最佳模型
- 修改route.ts集成新模块,替换原有关键词匹配逻辑

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-31 23:15:11 +08:00

348 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 智能意图分析器
* 分析用户输入,识别图片编辑意图
*
* 主要应用场景:图片编辑(抠图、换背景、增强等)
*/
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 };
}