fix(agent): prevent scene edit prompts from collapsing to white background
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-23 10:57:58 +08:00
parent 3d7f0c5485
commit b5e001dfc8

View File

@ -448,6 +448,52 @@ function shouldKeepBackgroundAsIs(originalPrompt: string, subIntent?: string): b
);
}
function isSceneLikeEditPrompt(originalPrompt: string): boolean {
return /(客厅|卧室|书房|办公室|室内|室外|场景|墙面|墙|地面|地板|窗帘|沙发|桌|椅|柜|装饰画|地毯)/i.test(
originalPrompt
);
}
function isStructuralEditRequest(originalPrompt: string): boolean {
return /(替换|换成|换到|互换|交换|移动|移到|挪到|位置|放到|放在|贴紧|靠左|靠右|顶部|底部|左侧|右侧|对齐|其他.*不变|其余.*不变)/i.test(
originalPrompt
);
}
function isPureEnhanceRequest(originalPrompt: string): boolean {
return /(清晰|画质|锐化|降噪|高清|修复|增强|去噪|超分)/i.test(originalPrompt);
}
function shouldForcePreciseEditFromEnhance(params: {
originalPrompt: string;
subIntent?: string;
}): boolean {
if (params.subIntent !== "enhance") return false;
return (
isStructuralEditRequest(params.originalPrompt) &&
!isPureEnhanceRequest(params.originalPrompt)
);
}
function buildPreciseEditPromptFromUserIntent(originalPrompt: string): string {
const base = `局部编辑:${originalPrompt}。要求:仅修改用户指定对象与位置关系;完整保留原场景背景(墙面、地面、家具、装饰)和光影,不要删除背景元素或抠成白底;主体比例、材质纹理、透视关系保持一致。`;
return ensureNanoBananaPromptStructure(base, "image_edit");
}
function extractOptimizedPromptFromNonJson(raw: string): string | null {
const text = String(raw || "")
.replace(/```[\s\S]*?```/g, " ")
.replace(/\s+/g, " ")
.trim();
if (!text) return null;
const labeledMatch = text.match(/(?:优化后的提示词|optimizedPrompt)\s*[::]\s*([\s\S]+)/i);
const candidate = (labeledMatch?.[1] || text).trim();
if (candidate.length < 12) return null;
return candidate.slice(0, 1400);
}
function shouldKeepCameraAsIs(originalPrompt: string): boolean {
return !/(角度|视角|机位|镜头|构图|俯拍|仰拍|侧拍|旋转|翻转|远景|近景|特写)/i.test(
originalPrompt
@ -462,12 +508,15 @@ function enforceImageEditStability(params: {
}) {
const keepBackground = shouldKeepBackgroundAsIs(params.originalPrompt, params.subIntent);
const keepCamera = shouldKeepCameraAsIs(params.originalPrompt);
const sceneLikePrompt = isSceneLikeEditPrompt(params.originalPrompt);
const stabilityRules = [
"只修改用户明确要求的内容,其他元素保持不变",
keepCamera ? "保持原图拍摄角度、主体朝向、构图和透视关系不变" : "",
keepBackground
? "保持原图背景颜色与明暗不变;若原图是白底,继续保持纯白背景(#FFFFFF)"
? sceneLikePrompt
? "保持原图背景颜色与明暗不变,禁止删除墙面/地面/家具背景,禁止将场景误改成纯白底"
: "保持原图背景颜色与明暗不变"
: "",
"保持主体形状比例、材质纹理和光影一致,禁止出现黑底/灰底污染",
].filter(Boolean);
@ -475,10 +524,19 @@ function enforceImageEditStability(params: {
const mergedNegativePrompt = [
params.negativePrompt || "",
keepCamera ? "角度变化,构图漂移,主体旋转" : "",
keepBackground ? "背景变黑,背景变灰,背景误改,白底丢失" : "",
keepBackground
? sceneLikePrompt
? "背景变黑,背景变灰,背景误改,墙面消失,地面消失,场景白底化"
: "背景变黑,背景变灰,背景误改"
: "",
"主体变形,比例错误,材质改变,边缘脏污",
]
.filter(Boolean)
.join(",")
.split(",")
.map((item) => item.trim())
.filter(Boolean)
.filter((item, index, list) => list.indexOf(item) === index)
.join(",");
const promptWithStability = `${params.optimizedPrompt.trim()}\n\n保真约束:${stabilityRules.join(";")}。`;
@ -651,6 +709,30 @@ export async function optimizePromptWithLLM(params: {
};
}
const extractedPrompt = extractOptimizedPromptFromNonJson(responseText);
if (extractedPrompt) {
console.log("[Prompt Optimizer LLM] Parse failed, using non-JSON optimized text fallback");
const normalizedPrompt = ensureNanoBananaPromptStructure(extractedPrompt, intent);
const stabilized =
intent === "image_edit"
? enforceImageEditStability({
optimizedPrompt: normalizedPrompt,
originalPrompt,
subIntent,
negativePrompt: "模糊,低质量,变形,失真,背景误改,主体变形",
})
: {
optimizedPrompt: normalizedPrompt,
negativePrompt: "模糊,低质量,变形,失真",
};
return {
originalPrompt,
optimizedPrompt: stabilized.optimizedPrompt,
negativePrompt: stabilized.negativePrompt,
friendlyMessage: intent === "image_edit" ? FRIENDLY_MESSAGES[subIntent || ""]?.template : undefined,
};
}
// 解析失败,回退到模板优化
console.log(
"[Prompt Optimizer LLM] Parse failed, falling back to template. raw=",
@ -700,6 +782,25 @@ export function optimizePrompt(params: {
};
}
if (shouldForcePreciseEditFromEnhance({ originalPrompt, subIntent })) {
const optimizedPrompt = buildPreciseEditPromptFromUserIntent(originalPrompt);
const stabilized = enforceImageEditStability({
optimizedPrompt,
originalPrompt,
subIntent,
negativePrompt:
"背景误改,墙面消失,地面消失,场景白底化,构图漂移,主体变形,比例错误,材质改变",
});
const result: OptimizeResult = {
originalPrompt,
optimizedPrompt: stabilized.optimizedPrompt,
negativePrompt: stabilized.negativePrompt,
friendlyMessage: "收到,我按你的对象替换/位置调整要求精确执行。",
};
console.log("[Prompt Optimizer] Output (enhance->precise-edit override):", result);
return result;
}
const template = EDIT_TEMPLATES[subIntent] as any;
if (!template) {
console.log("[Prompt Optimizer] No template for subIntent:", subIntent);