降低Agent追问并按Nano Banana三段式优化提示词
This commit is contained in:
parent
f0ede6f0c9
commit
31e4ca6407
@ -1397,6 +1397,31 @@ export async function POST(request: Request) {
|
||||
const streamId = generateUUID();
|
||||
await createStreamId({ streamId, chatId: id });
|
||||
|
||||
if (shouldRunAgentConversation && smartAutoNeedsClarification) {
|
||||
const hasCurrentImageInput = message.parts.some((part: any) =>
|
||||
part?.type === "file" || part?.type === "image" || part?.type === "image_url"
|
||||
);
|
||||
const hasHistoryImageInput = smartAutoHistoryImages.length > 0;
|
||||
const latestUserText = message.parts
|
||||
.filter((part): part is { type: "text"; text: string } => part.type === "text")
|
||||
.map((part) => part.text)
|
||||
.join(" ")
|
||||
.trim();
|
||||
|
||||
if (hasCurrentImageInput || hasHistoryImageInput || latestUserText.length > 0) {
|
||||
smartAutoNeedsClarification = false;
|
||||
smartAutoClarificationQuestion = undefined;
|
||||
if (
|
||||
!smartAutoFriendlyMessage ||
|
||||
/[??]$/.test(smartAutoFriendlyMessage.trim()) ||
|
||||
/哪一张|哪个|请先确认/.test(smartAutoFriendlyMessage)
|
||||
) {
|
||||
smartAutoFriendlyMessage = "收到,我将按你的当前需求直接执行。";
|
||||
}
|
||||
console.log("[Smart Auto Mode] ✅ Force direct execution (skip clarification)");
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRunAgentConversation && smartAutoNeedsClarification) {
|
||||
const clarificationMessage =
|
||||
smartAutoClarificationQuestion ||
|
||||
|
||||
@ -199,6 +199,12 @@ const LLM_OPTIMIZER_SYSTEM_PROMPT = `你是一个专业的AI图片编辑提示
|
||||
"negativePrompt": "需要避免的效果"
|
||||
}
|
||||
|
||||
## Nano Banana Pro 三段式模板(官方最佳实践)
|
||||
optimizedPrompt 必须按以下结构输出:
|
||||
目标:一句话说明最终要生成/修改的结果
|
||||
约束:一句话说明必须保持不变和禁止项
|
||||
细节:一句话补充构图、光线、材质、风格等关键细节
|
||||
|
||||
## 示例
|
||||
|
||||
用户请求:"把椅子颜色改成绿色"
|
||||
@ -252,6 +258,10 @@ const IMAGE_GEN_OPTIMIZER_SYSTEM_PROMPT = `你是一个专业的图片生成提
|
||||
4. negativePrompt 要包含:畸形、模糊、水印、文字错乱、额外主体、比例错误等。
|
||||
5. 输出简洁可执行,不要解释过程。
|
||||
6. 参数建议必须服务于“首图命中率”:人物全身/竖构图偏 9:16,横向场景偏 16:9,未明确时可用 auto。
|
||||
7. 按 Nano Banana Pro 官方三段式写法组织提示词:
|
||||
- 目标:一句话写清最终画面
|
||||
- 约束:一句话写清必须保持不变与禁止项
|
||||
- 细节:一句话补充风格/材质/光线/构图
|
||||
`;
|
||||
|
||||
function parseOptimizerJson(responseText: string): {
|
||||
@ -316,6 +326,33 @@ function sanitizeSuggestedParams(input?: {
|
||||
return Object.keys(output).length > 0 ? output : undefined;
|
||||
}
|
||||
|
||||
function ensureNanoBananaPromptStructure(prompt: string, intent: string): string {
|
||||
const clean = prompt.replace(/\s+/g, " ").trim();
|
||||
if (!clean) return prompt;
|
||||
if (/目标[::].+约束[::].+细节[::]/s.test(clean)) {
|
||||
return clean
|
||||
.replace(/\s*目标[::]\s*/g, "目标:")
|
||||
.replace(/\s*约束[::]\s*/g, "\n约束:")
|
||||
.replace(/\s*细节[::]\s*/g, "\n细节:");
|
||||
}
|
||||
|
||||
const fragments = clean
|
||||
.split(/[。!?!?]/)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
const goal = fragments[0] || clean;
|
||||
const defaultConstraint =
|
||||
intent === "image_edit"
|
||||
? "仅修改用户要求的部分,保持构图、主体比例、背景和光影关系稳定"
|
||||
: "保持主体比例与构图稳定,避免多余元素、变形和文字错误";
|
||||
const constraint = fragments[1] || defaultConstraint;
|
||||
const detail =
|
||||
fragments.slice(2).join(",") ||
|
||||
"材质真实、边缘清晰、光线自然、色彩准确,输出商业可用效果";
|
||||
|
||||
return `目标:${goal}\n约束:${constraint}\n细节:${detail}`;
|
||||
}
|
||||
|
||||
function shouldKeepBackgroundAsIs(originalPrompt: string, subIntent?: string): boolean {
|
||||
if (subIntent === "replace_background" || subIntent === "remove_background") {
|
||||
return false;
|
||||
@ -368,11 +405,12 @@ function enforceImageEditStability(params: {
|
||||
|
||||
function fallbackImageGenPrompt(originalPrompt: string): OptimizeResult {
|
||||
const normalized = originalPrompt.replace(/\s+/g, " ").trim();
|
||||
const optimizedPrompt = [
|
||||
const basePrompt = [
|
||||
"高质量图像生成:",
|
||||
normalized,
|
||||
"要求:主体清晰,构图平衡,光影自然,材质真实,细节丰富,整体风格统一。",
|
||||
].join(" ");
|
||||
const optimizedPrompt = ensureNanoBananaPromptStructure(basePrompt, "image_gen");
|
||||
|
||||
return {
|
||||
originalPrompt,
|
||||
@ -492,13 +530,19 @@ export async function optimizePromptWithLLM(params: {
|
||||
const stabilized =
|
||||
intent === "image_edit"
|
||||
? enforceImageEditStability({
|
||||
optimizedPrompt: parsedResult.optimizedPrompt || originalPrompt,
|
||||
optimizedPrompt: ensureNanoBananaPromptStructure(
|
||||
parsedResult.optimizedPrompt || originalPrompt,
|
||||
intent
|
||||
),
|
||||
originalPrompt,
|
||||
subIntent,
|
||||
negativePrompt: parsedResult.negativePrompt || "模糊,低质量,变形,失真",
|
||||
})
|
||||
: {
|
||||
optimizedPrompt: parsedResult.optimizedPrompt || originalPrompt,
|
||||
optimizedPrompt: ensureNanoBananaPromptStructure(
|
||||
parsedResult.optimizedPrompt || originalPrompt,
|
||||
intent
|
||||
),
|
||||
negativePrompt: parsedResult.negativePrompt || "模糊,低质量,变形,失真",
|
||||
};
|
||||
return {
|
||||
@ -548,9 +592,10 @@ export function optimizePrompt(params: {
|
||||
|
||||
// 如果没有子意图,返回通用优化
|
||||
if (!subIntent) {
|
||||
const basePrompt = `图片编辑:${originalPrompt}。要求:效果自然,画质清晰,细节完整。`;
|
||||
return {
|
||||
originalPrompt,
|
||||
optimizedPrompt: `图片编辑:${originalPrompt}。要求:效果自然,画质清晰,细节完整。`,
|
||||
optimizedPrompt: ensureNanoBananaPromptStructure(basePrompt, intent),
|
||||
negativePrompt: "模糊,低质量,变形,水印,失真,不自然",
|
||||
};
|
||||
}
|
||||
@ -605,6 +650,7 @@ export function optimizePrompt(params: {
|
||||
if (originalPrompt.length > 10 && !optimizedPrompt.includes(originalPrompt)) {
|
||||
optimizedPrompt = `${optimizedPrompt}\n\n用户补充要求:${originalPrompt}`;
|
||||
}
|
||||
optimizedPrompt = ensureNanoBananaPromptStructure(optimizedPrompt, intent);
|
||||
|
||||
// 生成友好的对话消息
|
||||
let friendlyMessage = "";
|
||||
|
||||
@ -23,6 +23,50 @@ export interface AnalysisResult {
|
||||
conversationalReply?: string; // 🆕 自然对话回复
|
||||
}
|
||||
|
||||
function inferDefaultImageEditSubIntent(text: string): AnalysisResult["subIntent"] {
|
||||
const lowerText = text.toLowerCase();
|
||||
if (/抠图|去背景|透明背景|去背|扣图|移除背景/.test(lowerText)) return "remove_background";
|
||||
if (/换背景|改背景|背景换成|背景改成|白底|透明底/.test(lowerText)) return "replace_background";
|
||||
if (/风格|卡通|动漫|油画|像素风|写实|插画/.test(lowerText)) return "style_transfer";
|
||||
if (/颜色|调色|亮度|对比度|饱和度|改成.*色|换成.*色/.test(lowerText)) return "color_adjust";
|
||||
if (/去除|消除|擦掉|删除|移除|p掉|重绘/.test(lowerText)) return "inpaint";
|
||||
return "enhance";
|
||||
}
|
||||
|
||||
function applyDirectExecutionPolicy(
|
||||
result: AnalysisResult,
|
||||
params: {
|
||||
text: string;
|
||||
hasImage: boolean;
|
||||
imageUrls?: string[];
|
||||
imageFromHistory?: boolean;
|
||||
}
|
||||
): AnalysisResult {
|
||||
const hasUsableImage =
|
||||
params.hasImage || Boolean(params.imageFromHistory) || (params.imageUrls?.length || 0) > 0;
|
||||
if (!hasUsableImage) return result;
|
||||
|
||||
const compactText = params.text.replace(/\s+/g, "").trim();
|
||||
const hasAnyRequestText = compactText.length > 0;
|
||||
const normalizedIntent = result.intent === "chat" || result.intent === "vision" ? "image_edit" : result.intent;
|
||||
const normalizedSubIntent =
|
||||
normalizedIntent === "image_edit"
|
||||
? result.subIntent || inferDefaultImageEditSubIntent(params.text)
|
||||
: result.subIntent;
|
||||
|
||||
return {
|
||||
...result,
|
||||
intent: normalizedIntent,
|
||||
subIntent: normalizedSubIntent,
|
||||
confidence: Math.max(result.confidence, 0.72),
|
||||
needsClarification: false,
|
||||
clarifyingQuestions: [],
|
||||
conversationalReply:
|
||||
result.conversationalReply ||
|
||||
(hasAnyRequestText ? "收到,我会按你的描述直接执行生成。" : "收到图片,我先按保真优化策略直接执行生成。"),
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeIntentForImageContext(
|
||||
result: AnalysisResult,
|
||||
text: string,
|
||||
@ -57,6 +101,7 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用
|
||||
1. 理解用户想要对图片做什么
|
||||
2. 用自然、友好的语气回复用户,告诉他你理解了他的需求并会帮他处理
|
||||
3. 同时输出结构化的意图分析结果
|
||||
4. 默认直接执行,不要反问用户;只有在完全无图且需求为空时才允许澄清
|
||||
|
||||
## 意图分类
|
||||
|
||||
@ -102,7 +147,7 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用
|
||||
- conversationalReply 要自然、友好、简洁
|
||||
- 可以加一些语气词让对话更亲切,如"好的"、"没问题"、"~"等
|
||||
- 说明你理解了什么需求,让用户知道你在做什么
|
||||
- 如果意图不明确,礼貌地询问用户想要什么效果
|
||||
- 有图片时优先直接执行,不要提问
|
||||
- 如果提供了画布上下文,仅用于理解,不要在 conversationalReply 中复述坐标或技术细节
|
||||
|
||||
## 示例
|
||||
@ -127,9 +172,10 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用
|
||||
用户发了图片但没说要做什么:
|
||||
{
|
||||
"intent": "image_edit",
|
||||
"confidence": 0.5,
|
||||
"conversationalReply": "我看到你发了一张图片,你想对它做什么处理呢?比如抠图、换背景、变清晰?",
|
||||
"needsClarification": true
|
||||
"subIntent": "enhance",
|
||||
"confidence": 0.72,
|
||||
"conversationalReply": "收到图片,我先做保真优化并输出结果,你可以再继续细化要求~",
|
||||
"needsClarification": false
|
||||
}
|
||||
|
||||
连续对话场景 - 用户说"换成蓝色"(系统自动使用历史图片):
|
||||
@ -146,9 +192,8 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI图片编辑助手。用
|
||||
"intent": "image_edit",
|
||||
"subIntent": "redo",
|
||||
"confidence": 0.8,
|
||||
"conversationalReply": "没问题,你想怎么调整呢?比如换个颜色、调整风格?",
|
||||
"needsClarification": true,
|
||||
"clarifyingQuestions": ["你具体想调整哪方面呢?"]
|
||||
"conversationalReply": "没问题,我先按上一轮目标继续优化并给你一个更稳的版本~",
|
||||
"needsClarification": false
|
||||
}
|
||||
|
||||
连续对话场景 - 用户说"再清晰一点":
|
||||
@ -191,7 +236,7 @@ export async function analyzeIntent(params: {
|
||||
const quickResult = quickKeywordMatch(text, hasImage);
|
||||
if (quickResult.confidence >= 0.9) {
|
||||
console.log("[Smart Analyzer] Quick match result:", quickResult);
|
||||
return quickResult;
|
||||
return applyDirectExecutionPolicy(quickResult, { text, hasImage, imageUrls, imageFromHistory });
|
||||
}
|
||||
|
||||
// 尝试使用 Qwen3 VL 进行深度分析(传入历史对话)
|
||||
@ -199,7 +244,7 @@ export async function analyzeIntent(params: {
|
||||
const llmResult = await analyzWithLLM(text, hasImage, imageUrls, historyMessages, context);
|
||||
if (llmResult) {
|
||||
console.log("[Smart Analyzer] LLM analysis result:", llmResult);
|
||||
return llmResult;
|
||||
return applyDirectExecutionPolicy(llmResult, { text, hasImage, imageUrls, imageFromHistory });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[Smart Analyzer] LLM analysis failed:", error);
|
||||
@ -208,7 +253,7 @@ export async function analyzeIntent(params: {
|
||||
// 回退到完整关键词分析
|
||||
const fallbackResult = fallbackKeywordAnalysis(text, hasImage);
|
||||
console.log("[Smart Analyzer] Fallback result:", fallbackResult);
|
||||
return fallbackResult;
|
||||
return applyDirectExecutionPolicy(fallbackResult, { text, hasImage, imageUrls, imageFromHistory });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -461,9 +506,10 @@ export function fallbackKeywordAnalysis(
|
||||
if (/修图|P图|改图|调图|处理.*图|编辑.*图|优化.*图/.test(lowerText)) {
|
||||
return {
|
||||
intent: "image_edit",
|
||||
subIntent: inferDefaultImageEditSubIntent(text),
|
||||
confidence: 0.8,
|
||||
needsClarification: true,
|
||||
conversationalReply: "我看到你想编辑这张图片,你具体想要做什么处理呢?比如抠图、换背景、变清晰?",
|
||||
needsClarification: false,
|
||||
conversationalReply: "收到,我先按你的需求直接执行图片优化。",
|
||||
};
|
||||
}
|
||||
|
||||
@ -479,9 +525,10 @@ export function fallbackKeywordAnalysis(
|
||||
// 有图但意图不明确
|
||||
return {
|
||||
intent: "image_edit",
|
||||
confidence: 0.5,
|
||||
needsClarification: true,
|
||||
conversationalReply: "我看到你发了一张图片,你想对它做什么处理呢?比如抠图、换背景、变清晰?",
|
||||
subIntent: inferDefaultImageEditSubIntent(text),
|
||||
confidence: 0.75,
|
||||
needsClarification: false,
|
||||
conversationalReply: "收到图片,我先按保真优化策略直接执行。",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user