baseline: Clover 独立仓库首次基线提交

将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。
当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包),
M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yangqianqian
2026-06-16 11:30:22 +08:00
commit 6a2632da70
253 changed files with 27467 additions and 0 deletions

View File

@@ -0,0 +1,174 @@
"""
角色差异化分镜模板
扒自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": "手背或指尖涂抹质地微距,产品放在旁边,自然光,保留真实皮肤纹理,能看清延展和肤感",
"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