全能创作:换款双形态与素材闸门防跳过

本地上传优先于商品库推荐;点击换款支持只出手/角色日常;角色未锁定禁止进核心卖点,「你来推荐」空库不再假完成。
This commit is contained in:
Azmat@qq.com
2026-09-20 09:28:31 +08:00
parent b5d970a4b5
commit f2e8a5f3c1
5 changed files with 638 additions and 67 deletions
+44 -10
View File
@@ -9,12 +9,18 @@ key 必须是同一个中文名(会话建的时候原样存进 CreationConversat
from __future__ import annotations
CLICK_SWAP_PRESETS = frozenset({"点击换款", "点触换款", "多色商品换款"})
_CLICK_SWAP_GUIDANCE = (
"固定机位的商品点击换款短片。必须先确认要展示的颜色/款式/SKU 及顺序,"
_CLICK_SWAP_FINGER_GUIDANCE = (
"形态:只出手指出镜。固定机位的商品点击换款短片。必须先确认要展示的颜色/款式/SKU 及顺序,"
"画面只围绕同一件商品的逐款切换:商品始终居中、大小与角度不变,背景、灯光、机位不变。"
"每次画面中的手指点击/轻触商品后,下一款在原位立即完成干净的 match cut 切换。"
"禁止改成口播剧情使用教程、多场景展示、换人或商品飞舞变形;最后才用同一构图做全款式收束。"
"禁止完整人物出镜、禁止生成角色定妆图、禁止改成口播/剧情/使用教程;最后才用同一构图做全款式收束。"
)
_CLICK_SWAP_CHARACTER_GUIDANCE = (
"形态:角色在日常使用场景中变色换款。锁定同一位角色与同一生活场景,角色自然使用或展示商品;"
"商品颜色/款式必须按用户确认顺序切换,人物五官、发型、身形、基础服装与场景保持一致。"
"允许自然动作与生活感,但不要改成口播带货腔、复杂剧情反转或频繁换景;结尾给出全款式收束。"
)
_CLICK_SWAP_GUIDANCE = _CLICK_SWAP_FINGER_GUIDANCE # 未选形态前的默认提示
VIDEO_PRESETS: dict[str, str] = {
"痛点解决演示": (
@@ -308,35 +314,63 @@ def preset_workflow_guidance(name: str) -> str:
return VIDEO_PRESET_WORKFLOWS.get((name or "").strip(), "")
def video_preset_delivery_contract(name: str) -> str:
_CLICK_SWAP_FINGER_CONTRACT = (
"【预设执行层·点击换款·只出手】这不是口播片、剧情片或普通商品展示片。"
"使用单一固定机位和同一背景,商品全程处于完全相同的中心位置、尺寸、角度与透视。"
"每个切换节点都必须清楚拍到一根手指轻触/点击商品,接触瞬间通过原位 match cut 换成下一款;"
"不改场景、不改机位、不运镜、不说话、不出现完整人物、不演剧情、不演示使用步骤、不生成角色定妆图。"
"各款必须按用户确认的顺序逐一出现,不自行发明颜色或款式;结尾停在干净的全款式总览。"
)
_CLICK_SWAP_CHARACTER_CONTRACT = (
"【预设执行层·点击换款·角色日常换款】锁定同一位角色与同一日常使用场景。"
"角色在自然生活动作中展示/使用商品,商品颜色或款式按用户确认顺序切换;"
"人物五官、发型、年龄感、身形与基础服装全程一致,场景与光线保持连贯。"
"允许生活感动作,禁止口播带货腔、复杂剧情反转、频繁换景或随机换人;结尾给出全款式收束。"
)
def video_preset_delivery_contract(name: str, *, click_swap_mode: str = "") -> str:
"""预设名 → 最终视频生成阶段必须执行的结构与镜头约束。"""
return VIDEO_PRESET_DELIVERY_CONTRACTS.get((name or "").strip(), "")
preset = (name or "").strip()
if preset in CLICK_SWAP_PRESETS:
if (click_swap_mode or "").strip() == "character":
return _CLICK_SWAP_CHARACTER_CONTRACT
return _CLICK_SWAP_FINGER_CONTRACT
return VIDEO_PRESET_DELIVERY_CONTRACTS.get(preset, "")
def is_click_swap_preset(name: str) -> bool:
return (name or "").strip() in CLICK_SWAP_PRESETS
def apply_video_preset_prompt(name: str, prompt: str) -> str:
def apply_video_preset_prompt(name: str, prompt: str, *, click_swap_mode: str = "") -> str:
"""把视频预设确定性并入最终出片指令,避免只依赖对话模型主动复述。"""
base = str(prompt or "").strip()
preset = (name or "").strip()
contract = video_preset_delivery_contract(preset)
mode = (click_swap_mode or "").strip()
contract = video_preset_delivery_contract(preset, click_swap_mode=mode)
if not base or not contract:
return base
marker = f"【视频预设】{preset}"
if marker in base:
return base
if is_click_swap_preset(preset):
# 换款是镜头结构,不是可有可无的风格词。把强制执行层放在前面,
# 原始 Agent Prompt 只作为商品/SKU 事实来源;其中若有口播、剧情、运镜或换场景等拍法,不得执行。
if mode == "character":
return (
f"{marker}\n{contract}\n\n"
"【原始商品与 SKU 信息】仅提取下文中的商品外观、颜色、款式、顺序与角色/场景事实;"
"下文任何与「同一角色、同一日常场景、按序换款」冲突的拍法一律忽略。\n"
f"{base}\n\n"
"【最终执行检查】全片锁定同一位角色与同一生活场景;"
"商品颜色/款式严格按确认顺序切换,禁止随机换人、口播带货腔或复杂剧情反转。"
)
return (
f"{marker}\n{contract}\n\n"
"【原始商品与 SKU 信息】仅提取下文中的商品外观、颜色、款式和顺序事实;"
"下文任何与「固定机位、手指点击、商品原位换款」冲突的拍法一律忽略。\n"
f"{base}\n\n"
"【最终执行检查】每一次换款都必须由画面内手指的一次清晰点击触发,"
"切换前后商品中心点、尺寸、角度、背景、光线和机位不变。"
"切换前后商品中心点、尺寸、角度、背景、光线和机位不变;不出现完整人物、不生成角色图"
)
return f"{base}\n\n{marker}\n{contract}"