fix: route detail replacement scene prompts correctly
This commit is contained in:
parent
5e896b8e56
commit
5aab184a97
@ -324,9 +324,11 @@ type ReplacementReferenceDecisionCore = Omit<
|
||||
>;
|
||||
|
||||
const DETAIL_WHITE_LAYOUT_HINT_PATTERN =
|
||||
/白底|浅色底|留白|产品说明|参数|规格|卖点|标签|说明图|信息图|海报|版式|排版|文字|标题|编号|材质|工艺|桌腿|木蜡油|代名词|典雅|高贵/i;
|
||||
/白底|浅色底|大面积留白|产品说明|参数图|规格图|卖点图|标签排版|说明图|信息图|海报|版式图|排版页|文字页|标题页|编号|尺寸|规格|厘米|\bcm\b/i;
|
||||
const DETAIL_STRONG_COPY_HINT_PATTERN =
|
||||
/白底|浅色底|产品说明|参数|规格|尺寸|卖点|标签|说明图|信息图|海报|版式|排版|文字|标题|编号|标注|材质标注|工艺标注|代名词|典雅|高贵/i;
|
||||
const DETAIL_PEOPLE_ACTION_HINT_PATTERN =
|
||||
/自拍|合照|拍照|拿手机|手机|聚会|好友|朋友|闺蜜|夫妻|情侣|家庭|亲子|陪伴|吃饭|用餐|举杯|互动|模特|人物|人像|多人|坐|站|走|逛|使用|体验/i;
|
||||
/自拍|合照|拍照|拿手机|手机自拍|聚会|好友|朋友|闺蜜|夫妻|情侣|家庭|亲子|陪伴|举杯|互动|模特|人物|人像|多人|人群|男士|女士|男人|女人|男生|女生|小孩|儿童|宝宝|顾客|吃饭的人|用餐的人|正在吃饭|坐在|站在|走动|行走|手持|试坐|倚靠/i;
|
||||
|
||||
export type ReplacementScenePlanningRuntime =
|
||||
| {
|
||||
@ -384,12 +386,16 @@ function ensureDetailReferenceGenerates<T extends ReplacementReferenceDecisionCo
|
||||
? "people_relation_locked"
|
||||
: scenePlan.copyImageCoupled || scenePlan.textPolicy === "lock"
|
||||
? "copy_locked_regenerate"
|
||||
: "layout_preserve_replace";
|
||||
: scenePlan.whiteBackgroundLikely
|
||||
? "layout_preserve_replace"
|
||||
: "prompt_pack_scene";
|
||||
const forcedReason = isStitchedReference
|
||||
? "拼合切片未勾选不处理,继续执行详情替换"
|
||||
: "详情替换未勾选不处理,继续执行必要替换";
|
||||
const forcedGenerationPrompt =
|
||||
"保留当前详情图的版式、文案、图标、构图和留白;先寻找可替换产品/产品展示区,没有产品则检查人物/模特展示,没有人物则根据上传图外观与参考图材质描述处理板材、材质、原材料、背景或视觉图片区,不允许整屏直出。";
|
||||
forcedRoute === "prompt_pack_scene"
|
||||
? "保留当前详情图的版式、文案、图标、构图和留白,但必须按前置工作流词包重建旧背景、空间、软装、灯光和产品场景;先寻找可替换产品/产品展示区,不允许整屏直出。"
|
||||
: "保留当前详情图的版式、文案、图标、构图和留白;先寻找可替换产品/产品展示区,没有产品则检查人物/模特展示,没有人物则根据上传图外观与参考图材质描述处理板材、材质、原材料、背景或视觉图片区,不允许整屏直出。";
|
||||
|
||||
return {
|
||||
decision: {
|
||||
@ -406,7 +412,7 @@ function ensureDetailReferenceGenerates<T extends ReplacementReferenceDecisionCo
|
||||
: scenePlan.generationRoute,
|
||||
promptPackPolicy:
|
||||
scenePlan.generationRoute === "direct_passthrough"
|
||||
? "forbid"
|
||||
? inferPromptPackPolicy(forcedRoute)
|
||||
: scenePlan.promptPackPolicy,
|
||||
textPolicy: scenePlan.textPolicy === "free" ? "preserve" : scenePlan.textPolicy,
|
||||
routeReason:
|
||||
@ -966,18 +972,26 @@ export function buildHeuristicReplacementScenePlan(params: {
|
||||
const isDetailReplacement = params.modeType === "detail_replacement";
|
||||
const isProductOnly = params.replacementStrategy === "product_only";
|
||||
const productImageSelection = buildDefaultProductImageSelection(params.productImageCount);
|
||||
const fallbackText = String(params.reason || "");
|
||||
const shouldProtectFallbackLayout =
|
||||
isDetailReplacement &&
|
||||
!isProductOnly &&
|
||||
(Boolean(params.visualProfile?.likelyWhiteLayout) ||
|
||||
DETAIL_STRONG_COPY_HINT_PATTERN.test(fallbackText));
|
||||
const generationRoute = params.shouldReplace
|
||||
? isProductOnly
|
||||
? "layout_preserve_replace"
|
||||
: isDetailReplacement
|
||||
? "layout_preserve_replace"
|
||||
? shouldProtectFallbackLayout
|
||||
? "layout_preserve_replace"
|
||||
: "prompt_pack_scene"
|
||||
: "prompt_pack_scene"
|
||||
: "direct_passthrough";
|
||||
const scenePlan: ReplacementScenePlan = {
|
||||
generationRoute,
|
||||
promptPackPolicy: inferPromptPackPolicy(generationRoute),
|
||||
textPolicy:
|
||||
generationRoute === "direct_passthrough" || isDetailReplacement
|
||||
generationRoute === "direct_passthrough" || shouldProtectFallbackLayout
|
||||
? "preserve"
|
||||
: "free",
|
||||
peoplePolicy: "none",
|
||||
@ -987,7 +1001,9 @@ export function buildHeuristicReplacementScenePlan(params: {
|
||||
? isProductOnly
|
||||
? "兜底按仅替换产品执行,不使用词包。"
|
||||
: isDetailReplacement
|
||||
? "兜底按详情版式保护执行,不使用词包,避免白底/强文案/人物页被误场景化。"
|
||||
? shouldProtectFallbackLayout
|
||||
? "兜底命中白底/说明/强文案特征,按详情版式保护执行,不使用词包。"
|
||||
: "兜底未命中白底、强文案或明确人物关系,按通用场景图执行词包场景替换。"
|
||||
: "兜底未检测到强约束,允许使用词包生成场景。"
|
||||
: params.reason,
|
||||
selectedProductImageIndexes: productImageSelection.selectedProductImageIndexes,
|
||||
@ -1001,7 +1017,9 @@ export function buildHeuristicReplacementScenePlan(params: {
|
||||
sceneSummary: params.shouldReplace
|
||||
? isProductOnly
|
||||
? "严格保留参考图的场景、文案和版式,只把产品展示区中的旧产品替换成输入产品。"
|
||||
: "保留参考图版式骨架、构图和主体位置,但把旧场景视觉内容按工作流目标风格重建。"
|
||||
: shouldProtectFallbackLayout
|
||||
? "保留参考图版式骨架、构图、文字和主体位置,只做必要的产品或视觉区替换。"
|
||||
: "保留参考图版式骨架、构图和主体位置,但把旧场景视觉内容按工作流目标风格重建。"
|
||||
: "当前参考图不满足替换条件。",
|
||||
cameraSummary: "保持参考图原有机位、构图和景别,不做整体重画。",
|
||||
placementSummary: isProductOnly
|
||||
@ -1012,15 +1030,21 @@ export function buildHeuristicReplacementScenePlan(params: {
|
||||
: "文字排版、标题区、分割线、留白和信息层级必须保留。",
|
||||
styleSummary: isProductOnly
|
||||
? "延续参考图原有风格、背景和氛围,不引入新的场景改造要求。"
|
||||
: "除版式骨架外,墙面、地面、背景家具、软装、灯光、摆件和空间氛围都要按工作流风格重建。",
|
||||
: shouldProtectFallbackLayout
|
||||
? "延续参考图原有版式和图文语义,不引入新的空间场景。"
|
||||
: "除版式骨架外,墙面、地面、背景家具、软装、灯光、摆件和空间氛围都要按工作流风格重建。",
|
||||
avoidSummary: isProductOnly
|
||||
? "不要改动背景、文案、按钮、图标、排版和装饰,不要重建整个场景,不要把多个产品角度同时塞进一张图。"
|
||||
: "不要只换产品不换场景,不要把参考图原有背景物件和空间氛围原样保留下来,不要把所有输入产品角度图同时强行出现在一张图中。",
|
||||
: shouldProtectFallbackLayout
|
||||
? "不要把白底/说明/强文案页场景化,不要新增厨房/客厅/人物/软装,不要让文字和图片失配。"
|
||||
: "不要只换产品不换场景,不要把参考图原有背景物件和空间氛围原样保留下来,不要把所有输入产品角度图同时强行出现在一张图中。",
|
||||
generationPrompt: params.shouldReplace
|
||||
? isProductOnly
|
||||
? `仅替换参考图中的产品主体,严格保留其余背景、文案、排版与光影关系。${params.reason}`
|
||||
: isDetailReplacement && shouldProtectFallbackLayout
|
||||
? `保留参考图的版式、文案、白底/留白和图文语义,不使用前置词包;只在产品、材质、板材、原材料或视觉图片区做必要替换。${params.reason}`
|
||||
: isDetailReplacement
|
||||
? `保留参考图的版式、文案、人物关系、白底/留白和图文语义,不使用前置词包;只在产品、材质、板材、原材料或视觉图片区做必要替换。${params.reason}`
|
||||
? `当前参考图按通用空间/场景详情页处理:必须使用前置工作流词包重建旧背景、空间、软装、灯光和产品场景,只保留参考图版式骨架、文字区、机位和信息层级。${params.reason}`
|
||||
: `以工作流目标风格重建当前这一屏的场景,只保留版式、机位、文字区与留白结构。${params.reason}`
|
||||
: params.reason,
|
||||
analysisModelName: null,
|
||||
@ -1030,7 +1054,7 @@ export function buildHeuristicReplacementScenePlan(params: {
|
||||
return applyDetailReplacementScenePlanGuards(scenePlan, {
|
||||
modeType: params.modeType,
|
||||
hasModelImage: params.hasModelImage,
|
||||
hasImportantText: isDetailReplacement,
|
||||
hasImportantText: shouldProtectFallbackLayout,
|
||||
containsPeople: false,
|
||||
containsMultiplePeople: false,
|
||||
visualProfile: params.visualProfile,
|
||||
|
||||
@ -3399,8 +3399,14 @@ export async function POST(request: Request) {
|
||||
scenePlanSource: replacementExecutionPlan.scenePlan.analysisSource,
|
||||
generationRoute: replacementExecutionPlan.scenePlan.generationRoute,
|
||||
promptPackPolicy: replacementExecutionPlan.scenePlan.promptPackPolicy,
|
||||
packPolicy: replacementExecutionPlan.scenePlan.promptPackPolicy,
|
||||
textPolicy: replacementExecutionPlan.scenePlan.textPolicy,
|
||||
peoplePolicy: replacementExecutionPlan.scenePlan.peoplePolicy,
|
||||
whiteLayout: replacementExecutionPlan.scenePlan.whiteBackgroundLikely,
|
||||
copyCoupled: replacementExecutionPlan.scenePlan.copyImageCoupled,
|
||||
useModelImage: replacementExecutionPlan.scenePlan.useModelImage,
|
||||
sourceProductImages: productInputImageUrls.length,
|
||||
sourceModelImage: Boolean(modelInputImageUrl),
|
||||
});
|
||||
const referenceSourceImageUrls = Array.from(
|
||||
new Set([
|
||||
@ -3442,6 +3448,19 @@ export async function POST(request: Request) {
|
||||
reference.imageUrl,
|
||||
]),
|
||||
);
|
||||
chatApiLogger.info("[Chat API] Direct detail replacement image generation started:", {
|
||||
referenceIndex: referenceIndex + 1,
|
||||
totalReferences: replacementReferences.length,
|
||||
referenceLabel: reference.label,
|
||||
generationRoute: replacementExecutionPlan.scenePlan.generationRoute,
|
||||
packPolicy: replacementExecutionPlan.scenePlan.promptPackPolicy,
|
||||
selectedProductImages: selectedProductContextImageUrls.length,
|
||||
sourceProductImages: productInputImageUrls.length,
|
||||
includeModelImage: shouldIncludeModelImage,
|
||||
sourceImageCount: sourceImageUrls.length,
|
||||
whiteLayout: replacementExecutionPlan.scenePlan.whiteBackgroundLikely,
|
||||
copyCoupled: replacementExecutionPlan.scenePlan.copyImageCoupled,
|
||||
});
|
||||
const replacementPrompt = buildAgentReplacementPrompt({
|
||||
basePrompt: baseReplacementPrompt,
|
||||
modeType: "detail_replacement",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user