Files
beige/backend/app/services/ai_engine/storyboard_templates.py
yangqianqian df1856d793 上线版: 产品表单统一+form嵌套修复+用户管理+部署+三套叙事
- 产品编辑入口统一走 ProductFormFull(卖点/风格/人群/品牌词全字段);
  修复开任务页 <form> 套 <form> 致"编辑产品"报错、改不了、跳回首个产品
- dashboard 入口卡片对齐实际路由: 系统管理(/config) 与 工作配置(/settings) 分开;
  settings ?tab=products 直达改用挂载后读 URL, 消除 hydration mismatch
- 新增用户管理(users API/admin service/改密页) + alembic 022/023/024
- 上线部署: Dockerfile / docker-compose.prod+https / nginx https / .env.example
- A8 三套正交叙事(痛点/场景/成分背书) + beige 调色去AI化 + 飞轮 text_import 高权重信号

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 18:08:13 +08:00

175 lines
9.6 KiB
Python
Raw Permalink 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.
"""
角色差异化分镜模板
扒自worker/src/image.js buildImageStoryboard storyboardByRole(222-321)
每个分镜角色有【各自不同】的画面/文字/构图策略,这是"小红书风格不雷同"的根因。
之前缩水6张共用同一个品类 proof 策略 → 图全长一样。
模板里 {占位} 在 storyboard.py 运行时按文案/卖点填充。
字段含义(对齐 promptFromStoryboard 9 字段):
goal 本张目标(这张图要让用户产生什么动作/情绪)
overlay 图上主文字模板(每张不同,不重复封面标题)
visual 画面主体(构图、景别、道具、光线——这是不雷同的关键)
basis 文案依据(这张图从文案哪里来,给模型锚点)
forbidden 本张禁止事项
"""
from __future__ import annotations
import re
# ── sanitize扒 sanitizeImagePlanText防违禁视觉词进 prompt
_SANITIZE_RULES: list[tuple[str, str]] = [
(r"before\s*&\s*after", "质地与使用状态说明"),
(r"before\s*/?\s*after", "质地与使用状态说明"),
(r"\bbefore\b", "使用前状态"),
(r"\bafter\b", "使用后状态"),
(r"使用前后|用前用后|用前后|前后对比|使用前|使用后", "质地/场景/使用状态说明"),
(r"功效对比|效果对比|改善对比", "质地/场景说明对比"),
(r"肤色变白|皮肤变白|变白|美白", "自然光泽感"),
(r"瑕疵消失|斑点消失|痘印消失|消除瑕疵|祛斑", "妆感更服帖"),
(r"治疗前后|治疗后|医美前后|治愈|修复受损", "日常使用场景说明"),
]
def sanitize_text(value: str, max_len: int = 56) -> str:
s = str(value)
for pattern, repl in _SANITIZE_RULES:
s = re.sub(pattern, repl, s, flags=re.IGNORECASE)
return re.sub(r"\s+", " ", s).strip()[:max_len]
# 北哥6张标准套 + 8张扩展角色每角色独立画面策略
ROLE_STORYBOARD_TPL: dict[str, dict] = {
"hook": {
"goal": "{audience}因为{pain}停下划走,产生点开欲",
"overlay": "{hook}",
"visual": "自然光生活场景,手持产品或产品在桌面前景,真实使用细节/手部细节像iPhone随手实拍的封面不是海报",
"basis": "来自选中文案标题、人群{audience}、痛点{pain}",
"forbidden": "不要价格、不要重复后续卖点、不要App界面、不要广告海报感",
},
"product_closeup": {
"goal": "建立单品记忆锚点,让用户记住是哪个产品",
"overlay": "{brand}",
"visual": "单品高清特写居中,干净浅色台面,柔和顶光,瓶身/包装/标签清晰可读且忠于参考图原样,品牌词只出现在图上标题/贴纸等文字排版层,绝不印到瓶身上",
"basis": "来自产品名和品牌词第2张和第6张都要带品牌词强化记忆",
"forbidden": "不要堆多个产品、不要花哨背景抢主体、不要改包装文字",
},
"ingredient": {
"goal": "用成分/配方/参数信息建立信任,但不夸大不医疗化",
"overlay": "看清{point}",
"visual": "信息卡片式布局,产品+成分/参数图标+短说明,浅色干净商务风,信息层级清楚(护肤食品讲成分配方,数码家居讲参数原理,服饰讲材质工艺)",
"basis": "来自卖点里的成分/参数/工艺点,理性表达不夸大",
"forbidden": "不要治疗/改善疾病承诺、不要医生背书、不要绝对化",
},
"texture": {
"goal": "让用户看到{point}的真实质感证据",
"overlay": "{point}看得见",
"visual": "质地/材质/细节微距,产品放在旁边,自然光,保留真实纹理(护肤=涂抹延展肤感,食品=色泽质地,服饰=面料织纹,数码家居=做工细节),能看清{point}",
"basis": "来自卖点里的质地/材质/做工描述",
"forbidden": "不要生成变白效果、不要医疗化对比、不要和封面同构图",
},
"applied_proof": {
"goal": "用可感知的真实使用证据证明{point}",
"overlay": "{proof_overlay}",
"visual": "{proof_visual}",
"basis": "来自核心卖点{point}和用户对效果的关注",
"forbidden": "{proof_forbidden}",
},
"closer": {
"goal": "用囤货/省钱情报/搜索暗号完成软性转化",
"overlay": "这波真的会囤 {brand}",
"visual": "拆箱、囤货角或产品放在日常物品旁,真实分享氛围,轻量搜索/品牌词暗号提示,再带一次品牌词引导成交",
"basis": "来自价格心智/选择理由,但不做硬广",
"forbidden": "不要大促价格牌、不要购买按钮、不要红黄电商风",
},
# ── 8张扩展角色 ──
"pain_scene": {
"goal": "让用户共鸣{pain}",
"overlay": "{pain}真的懂",
"visual": "{scene}里的真实困扰场景,产品作为解决方案线索出现,不做使用前后对比",
"basis": "来自文案痛点和目标人群",
"forbidden": "不要夸大焦虑、不要before/after",
},
"social_proof": {
"goal": "补足信任背书,让内容不像单方面推销",
"overlay": "身边人都在问",
"visual": "产品在包里/桌面/宿舍囤货角,配简短手写感反馈气泡,真实随手拍",
"basis": "来自评论区语言/选择理由,缺评论时用低调口碑表达",
"forbidden": "不要假造大量头像评论、不要App评论区截图",
},
"scenario": {
"goal": "展示{scene}以外的多场景使用代入",
"overlay": "这些场景都能用",
"visual": "2-3个生活小场景拼贴宿舍/通勤包/办公桌,产品贯穿其中,统一光线",
"basis": "来自目标人群的多场景使用需求",
"forbidden": "不要电商详情页拼贴、不要夸大效果",
},
"tutorial": {
"goal": "降低使用门槛,告诉用户怎么用",
"overlay": "三步就上手",
"visual": "三步手势教程:取量、点涂/使用、收尾,干净背景,产品在画面内",
"basis": "来自文案里的快速/懒人使用场景",
"forbidden": "不要复杂说明书、不要过多文字",
},
}
def role_template(role: str) -> dict:
"""取角色模板,未知角色用 applied_proof 兜底(和源头一致)"""
return ROLE_STORYBOARD_TPL.get(role, ROLE_STORYBOARD_TPL["applied_proof"])
# ── proofStrategy按品类定 applied_proof 证明页策略,扒 image.js:163-208
# 品类来自 product.category不硬编码枚举无匹配走"通用好物"兜底
PROOF_STRATEGIES: dict[str, dict] = {
"个护护理": {
"overlay_tpl": "{point}看得见",
"visual": "手部/身体局部使用证明:少量点涂、推开后吸收状态、真实纹理和自然光;产品只做辅助露出",
"asset_use": "优先使用实拍/参考图中的手部、干纹、涂抹、随身场景;产品图保证包装准确",
"forbidden": "不要变白、祛斑、医学效果、before/after字样不要和封面同构图",
},
"美妆护肤": {
"overlay_tpl": "{point}看得见",
"visual": "肤感/质地证明:手背、脸颊局部或质地微距,展示推开前后真实状态,保留皮肤纹理和自然光",
"asset_use": "优先使用实拍/参考图中的手背、上脸、质地素材;产品图辅助露出",
"forbidden": "不要变白、祛斑、医学效果、before/after字样不要和封面同构图",
},
"食品饮品": {
"overlay_tpl": "{point}一眼懂",
"visual": "冲泡/开袋/入口证明:展示包装、杯中状态、质地颜色或一口口感,真实桌面光线",
"asset_use": "产品图保证包装准确,参考图用于杯子、开袋、冲泡、办公室/居家场景",
"forbidden": "不要涂抹、不要护肤肤感、不要医疗健康承诺",
},
"营养健康": {
"overlay_tpl": "看清{point}",
"visual": "理性证明页:包装、成分表、使用场景和每日习惯卡片,信息清晰但不做治疗承诺",
"asset_use": "产品图和说明图用于成分/包装准确,参考图用于日常使用场景",
"forbidden": "不要治疗、改善疾病、速效、医生背书、前后对比",
},
"家居生活": {
"overlay_tpl": "{point}真省事",
"visual": "使用过程证明:展示痛点场景、产品介入和使用过程细节,强调顺手/收纳/效率",
"asset_use": "参考图用于真实家居环境,产品图保证外观准确",
"forbidden": "不要护肤涂抹,不要虚假夸大结果",
},
"服饰穿搭": {
"overlay_tpl": "{point}有细节",
"visual": "上身/材质证明:展示面料纹理、版型细节或普通身材上身局部,真实自然",
"asset_use": "参考图用于上身/搭配/材质,产品图保证款式颜色准确",
"forbidden": "不要护肤涂抹,不要过度精修模特感",
},
"通用好物": {
"overlay_tpl": "{point}清晰可见",
"visual": "产品使用场景证明:真实道具/场景,展示产品细节和使用过程",
"asset_use": "产品图保证准确,参考图用于场景辅助",
"forbidden": "不要夸大效果,不要硬广式价格牌",
},
}
def proof_strategy(category: str, point: str) -> dict:
"""取品类证明策略,无匹配用通用兜底(扒 proofStrategy"""
s = PROOF_STRATEGIES.get(category, PROOF_STRATEGIES["通用好物"]).copy()
s["overlay"] = s.pop("overlay_tpl", "{point}").format(point=point)
return s