Compare commits

...

21 Commits

Author SHA1 Message Date
CI Bot 154e480db0 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 10s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m5s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m9s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m10s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 28s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m6s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m40s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m53s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m8s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m15s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m35s
CI/CD Pipeline / Validate - Style (push) Successful in 4m31s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m14s
AI Code Review / AI Code Review (pull_request) Successful in 6m43s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m43s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m28s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m39s
CI/CD Pipeline / Validate - Security (push) Successful in 10m4s
CI/CD Pipeline / Unit Tests (push) Failing after 11m8s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-15 16:13:51 +00:00
xiaoxia 76c59e49e7 #2312 fix: alembic 113改为新增版本而非覆盖运营v6
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 6s
CI/CD Pipeline / Check push changed paths (push) Successful in 8s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m26s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m27s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m15s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m9s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m40s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m22s
CI/CD Pipeline / Integration Tests (push) Successful in 3m46s
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
原方案直接UPDATE active行system_prompt会覆盖运营手动修改。改为插入新版本(MAX+1)为active,旧版本完整保留仅is_active=false,运营可随时后台切回;复用旧active的user_prompt/example_output保留运营微调;幂等可重入;downgrade可删新行恢复旧active。
2026-10-16 00:07:35 +08:00
xiaoxia fed80115c2 #2312 文案创意大改:四铁律+短剧式结构+去广告化hint
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m59s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m6s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m19s
AI Code Review / AI Code Review (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m1s
CI/CD Pipeline / CI Gate (pull_request) Successful in 7s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
- prompts.py: 重写STORYBOARD_SYSTEM文案核心规则,新增【文案创作四铁律】
  * 铁律一开头3秒:禁自我介绍/亮广告身份,必须是正在发生的事
  * 铁律二内容:像真人讲故事,禁抽象词,卖点场景化数字具体化反差梗
  * 铁律三CTA:好奇心驱动,禁指令式硬推
  * 铁律四语言风格:短句口语,禁服务/广告/说教/主播四种腔调
  * 新增写作要求第11条:前3秒第一镜禁空镜/产品特写/logo开场
- viral_video.py:
  * _DEFAULT_VIRAL_STRUCTURE_HINTS新增3个短剧式爆款结构:
    短剧式冲突开场/反套路反转/悬念揭秘式
  * _DEFAULT_PERSONA_HINTS去广告化:去掉专业可信品牌形象建立权威感我干这行XX年
    等广告腔和铁律禁止开场,改为具体说话方式和切入角度
  * _marketing_purpose_hint去广告化:口播/种草/门店/品牌类hint从突出品牌优势/
2026-10-16 00:05:26 +08:00
CI Bot 6d40ca3b04 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 6s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m12s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m33s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m42s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m38s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m5s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m24s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m34s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m54s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 5m34s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m57s
AI Code Review / AI Code Review (pull_request) Successful in 7m11s
CI/CD Pipeline / Integration Tests (push) Failing after 7m14s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m11s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m38s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m32s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m39s
CI/CD Pipeline / Unit Tests (push) Failing after 13m19s
CI/CD Pipeline / Validate - Security (push) Successful in 15m6s
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-15 14:41:49 +00:00
xiaoxia 786d4946f3 style: auto-format [skip ci-format-check]
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 0s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m35s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m38s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m43s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m49s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m54s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m23s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m25s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m36s
CI/CD Pipeline / Integration Tests (push) Successful in 5m46s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m58s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m30s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m18s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
2026-10-15 22:34:24 +08:00
xiaoxia bb7464a937 feat(viral-video): #2312 prompt_loader加载实证日志--打印来源/version/name/sp前100字
每次缓存刷新(30s TTL miss)都打INFO日志,确认后台修改的模板是否真的被加载。
格式: [prompt_loader] 加载模板 type=xxx 来源=db/code-default version=N name=xxx is_active=True sp_preview='...'
2026-10-15 22:34:11 +08:00
xiaoxia b41217d3ba fix(viral-video): #2312 v6运营模板action_details为空修复——从visual中智能提取动作
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m50s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m16s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 48s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 48s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m52s
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m55s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m34s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m42s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m46s
CI/CD Pipeline / Integration Tests (push) Successful in 6m45s
AI Code Review / AI Code Review (pull_request) Successful in 7m20s
CI/CD Pipeline / Validate - Style (push) Successful in 7m26s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m34s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m47s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 9m53s
CI/CD Pipeline / Unit Tests (push) Failing after 19m12s
CI/CD Pipeline / Validate - Security (push) Successful in 19m56s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
v6运营模板把动作描述嵌入<visual>/<画面>字段,没有输出独立<action_details>标签。
修复三层兜底策略:
1. 新/老schema解析后,如果action_text为空但visual有内容,调用_split_visual_field从visual文本中提取动作片段,并把纯画面部分回填visual_text
2. 如果从visual里也拆不出独立动作子句,调用新增_infer_action_from_visual():
   - 先扫描visual中的短句找含手势/肢体动词的子句直接截取
   - 含人物关键词→返回人物口播默认动作(面向镜头微笑+手势讲解)
   - 纯商品/场景→返回镜头推进展示产品默认动作
3. cam_text也做兜底:为空时从visual里拆分出摄影参数片段
确保前端三字段shot/visual/action_details都有值,不再出现空字段。
2026-10-15 21:44:25 +08:00
CI Bot 2167444df0 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 16s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 18s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 22s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m44s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m50s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m1s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m55s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m38s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m32s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m54s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m30s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m43s
AI Code Review / AI Code Review (pull_request) Successful in 7m17s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m17s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m30s
CI/CD Pipeline / Validate - Style (push) Successful in 9m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 9m20s
CI/CD Pipeline / Integration Tests (push) Successful in 10m5s
CI/CD Pipeline / Unit Tests (push) Failing after 14m12s
CI/CD Pipeline / Validate - Security (push) Successful in 19m33s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-15 12:33:22 +00:00
xiaoxia 638213ab2a fix(viral-video): #2312 E2E四项修复 - XML标签别名兼容/review占位符/OSS ACL/Wan模型归一化
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 45s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 41s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m8s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m8s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m55s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m11s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m27s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m8s
CI/CD Pipeline / Integration Tests (push) Failing after 6m29s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m40s
AI Code Review / AI Code Review (pull_request) Successful in 6m58s
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
1. 分镜shot/action字段为空(问题1): _parse_script_xml扩展标签别名兼容,支持中文(镜头/画面/动作/台词/口播/角色/转场/BGM)和英文(camera/scene/dialogue/narration/description/action)变体,clip节点支持<镜头>/<scene>/<segment>别名,运营v6模板任何命名都能正确提取四个字段
2. Review占位符{fusion_result}不兼容(问题2): prompt_loader render_system_prompt和render_user_prompt统一注入占位符别名映射(voiceover_script→fusion_result/script/copy_text, storyboard_input→input_text/brief),DB里v1模板用{fusion_result}也能正确填充文案
3. 克隆音色样本OSS ACL private(问题3): upload_to_oss/storage.upload_file/upload_file_smart新增extra_headers参数,克隆样本上传点传x-oss-object-acl:public-read,DashScope/Wan/Seedance API可公网拉取
4. 选Wan 3.0实际用Seedance(问题4): get_viral_video_model_config增加多策略查找--精确key→归一化(去横杠/下划线/点/空格)匹配→model_id反向匹配→前缀兜底(含'wan'归wan-3.0),防止传wan3.0-video/model_id/大小写变体时误回落seedance-2.5
2026-10-15 20:26:17 +08:00
CI Bot 468f6b74a1 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (push) Successful in 7s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 54s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m1s
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m27s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m18s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m15s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m32s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m3s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m47s
CI/CD Pipeline / Integration Tests (push) Failing after 5m36s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m19s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m26s
AI Code Review / AI Code Review (pull_request) Successful in 7m3s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 7m32s
CI/CD Pipeline / Validate - Style (push) Successful in 9m33s
CI/CD Pipeline / Unit Tests (push) Failing after 13m6s
CI/CD Pipeline / Validate - Security (push) Successful in 19m38s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-15 11:45:55 +00:00
xiaoxia d1e9cf3ff4 feat(#2312): STEP2全部参数hint完整覆盖(10人设+19结构+8客群+5语言+20营销目的)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 0s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 57s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m9s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m18s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m37s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m40s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m20s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m33s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m51s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m56s
AI Code Review / AI Code Review (pull_request) Successful in 7m3s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
按前端ViralVideoPage.constants.ts逐项核查补齐:

人设(10个全补):
- 新增:通用个人IP/顾问型IP/创始人IP/创业者IP/从业者经验派/避坑顾问型/知识科普型/测评种草型
- 原有保留:老板型IP/专家型IP + 旧版备用(宝妈/店主/专业顾问等)

爆款结构(19个全补):
- 新增:痛点场景植入+给出通关秘籍/反常识开场+扎心现状+制造焦虑/核心难题+化解焦虑+描绘愿景/
  痛点前置+前后对比+给出期许/悬念拉满+揭露危害+明确目的/颠覆认知+现状拆解+赋予价值/
  结果先行+消除顾虑+保留悬念/真实困境+认知反转+传授秘籍/反差事实+案例佐证+戳破真相/
  预埋悬念+标杆案例+引出核心/危机渲染+放大痛点+输出干货/逆袭开场+成功诀窍+低价引流/
  反常识观点+分析危害+描述现状/正反对比+解析原因+简易方法/
  真实场景+内心刻画+共情引导+展望未来/连续否定+代入感受+打破认知+精准戳痛/
  揭秘行业+类比施压+放大焦虑+精准锁客
- 原有保留:反差破局/情绪共鸣+勾起好奇+拔高价值 等 + 旧版备用

目标客户(8个全补):
- 新增:小镇青年/精致妈妈/新锐白领/资深中产/都市蓝领专属hint
- 升级:Z世代/小镇中老年/都市银发从粗关键词匹配升级为专属档
- 不再依赖模糊的18-25/30-45/50+泛匹配,每类客群都有具体的用词/语气/心理描写

台词语言(5个全补):
- 前端传全名('中文(普通话)'/'粤语'/'英语'/'日语'/'韩语'),之前的zh-CN/en-us等code无法匹配
- 新增全名→code的alias映射,粤语加入'嘅/咗/嘞/喺/唔'等粤语助词指引
- 保留旧code兼容

营销目的(20个之前已全覆盖,保持不变)

所有未命中选项走的是'按该人设/结构/客群的口吻组织'这种通用废话,
LLM根本不知道怎么写具体风格。补齐后每个选项都有20-80字的具体写作指引,
明确告诉LLM:开头怎么写、中段怎么推进、结尾怎么收、用什么语气、
什么词不能用、观众心理抓什么点。
2026-10-15 19:38:36 +08:00
xiaoxia f4c611a21f fix(#2312): 克隆音色'应赐恩'完全未生效根因修复
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (push) Successful in 6s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 7s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m39s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m48s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m59s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m33s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m59s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m31s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
根因:前端选'我的音色'(克隆音色)时,voice_id传的是CosyVoice注册后的voice_id
(形如cosyvoice_xxx),而不是profile主键UUID。worker端_resolve_voice_sample_audio
只调用_repo.get(profile_id)按主键查,必然查不到→走_tts_voice_sample_fallback→
用默认女声合成长样本→视频里根本不是用户音色。同样的bug也出在_resolve_tts_voice_id。

修复:
1. _resolve_voice_sample_audio:_repo.get()查不到时,追加_repo.find_by_voice_id()兜底;
   空voice_source且voice_id是UUID格式时自动尝试克隆路径;全链路加详细日志
   (voice_id/voice_source/sample URL前120字),便于线上排查
2. _resolve_tts_voice_id(TTS兜底路径):同样加find_by_voice_id回退,保证TTS降级
   路径也能正确用克隆音色合成
3. _step_render入口加关键日志:打印voice_id/voice_source/ref_audio URL前120字,
   一眼看出是用了预置静态样本/克隆样本/TTS兜底
4. 预置音色分支加防御:voice_source空串但voice_id像UUID(克隆profile),继续走
   克隆路径而非直接降级TTS

注:问题1的Wan ratio参数名修复、问题4+5的营销参数hint补充、问题3样本质量升级
(10s/精确seek/24k/128k/淡入淡出)已在之前commit fde6c0b4提交。
本次只提交克隆音色查找修复。
2026-10-15 19:34:30 +08:00
CI Bot 4e4afd80e9 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m14s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m14s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m52s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m53s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m33s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-15 11:28:35 +00:00
xiaoxia 9dc4ff17a3 feat(#2312): alembic 112恢复运营v6模板为active,存档#2312 v5/v3/v7
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 33s
CI/CD Pipeline / Check push changed paths (push) Successful in 35s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 48s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m18s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m0s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m17s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m36s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m35s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m8s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m5s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m14s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m20s
AI Code Review / AI Code Review (pull_request) Successful in 7m22s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Failing after 13m37s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m29s
CI/CD Pipeline / Integration Tests (push) Failing after 6m45s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
- storyboard: 恢复 v6 is_active=true;v5(我们#2312保底) + v7(运营试配合规版) is_active=false存档
- review: 动态查找非v3的最高运营版本,恢复为active;v3(#2312保底) is_active=false存档
- 全部操作幂等(先检查行存在再update)
- v6不存在/库空等极端场景自动回退到v5/v3保底,不会把可用状态改坏
- 防御注入兜底(prompt_loader)对v6仍然生效,合规底线不丢
2026-10-15 19:07:14 +08:00
xiaoxia fde6c0b483 fix(#2312): 5项staging反馈修复
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 5s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m29s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m44s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m53s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m57s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m34s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m23s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m50s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m22s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
- [紧急] alembic 111改为保底插入策略,不deactivate运营在后台配置的v6等模板,合规底线靠prompt_loader防御注入兜底;downgrade只删本次插入的#2312版本
- prompt_loader防御注入增强:多指纹组合判定(合规类+医疗类双维度,industry_redlines扩展到4指纹),防止运营改措辞后漏判
- 问题1(9:16出横屏): Wan 3.0 API参数名错误 aspect_ratio→ratio(官方文档用ratio);并在Wan prompt头部加竖/横/正方形构图文字提示作为双保险
- 问题3(克隆音色不像): 音频样本8s→10s(Wan官方建议≥10s);ffmpeg -ss移到-i后精确seek(避免关键帧偏移);采样率16kHz→24kHz、码率96k→128k;首尾50ms淡入淡出防爆音
- 问题4+5(文案不按配置):
  - 补充专家型IP人设hint(行家第一人称、破误区、实在建议、不夸大)
  - 补充情绪共鸣+勾起好奇+拔高价值结构hint(三段式:戳心痛点→悬念引产品→温暖升华)
  - 情绪短片从短剧模式(多角色对话)拆出,改为情感共鸣模式(第一人称真情独白、情绪递进)
  - 小镇中老年/县城中老年/下沉市场客群单独hint(街坊拉家常、实在靠谱、怕踩坑、健康/子女/面子心理)
2026-10-15 19:02:29 +08:00
CI Bot 2ccfbe4a9c style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 6s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 7s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m13s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m35s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m42s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m46s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m37s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m5s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m12s
CI/CD Pipeline / Integration Tests (push) Failing after 3m34s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m36s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 4m40s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m2s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m58s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 5m51s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m45s
AI Code Review / AI Code Review (pull_request) Successful in 7m14s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m58s
CI/CD Pipeline / Validate - Security (push) Successful in 10m1s
CI/CD Pipeline / Unit Tests (push) Failing after 11m19s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-15 10:25:36 +00:00
xiaoxia 4766d9cacb fix(viral-video): #2312 修复DB模板与代码默认不同步导致合规规则静默失效
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 9s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m14s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m28s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m23s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m2s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m22s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m41s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m6s
CI/CD Pipeline / CI Gate (pull_request) Successful in 32s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m17s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
之前 #2308(三字段拆分)/#2311(音频重构)/#2312(合规红线) 多次更新 prompts.py
代码默认模板,但没有写 alembic migration 同步到 viral_video_prompt_templates
表——DB里仍停留在 108 迁移插入的 storyboard v4(多角色对话版,没有<shot>/
<visual>/<action_details>三字段拆分,更没有 GLOBAL_CONSTRAINTS/医疗红线/
{industry_redlines}占位符)+ review v1保底版,生产环境实际跑的是旧模板,
新加的合规规则全部不生效。

修复:
1. 新增 alembic 111:deactivate旧storyboard/review→插入v5 storyboard
   (三字段拆分+GLOBAL_CONSTRAINTS+{industry_redlines}占位符+8条硬约束+
   NEGATIVE_RULES医疗禁令) + v3 review(医疗/养生/健康红线5维度审核)
2. prompt_loader.render_system_prompt 加防御性注入:DB模板若缺少
   '不承诺效果'指纹则自动追加GLOBAL_CONSTRAINTS;若缺少{industry_redlines}
   占位符则把传入的红线内容直接追加到末尾。避免未来再出现'代码加了规则
   但DB旧模板没带'的静默失效(双保险)。

文件:
- alembic/versions/111_vv_compliance_prompts.py: 新迁移,升级storyboard到v5/review到v3
- packages/application/viral_video/prompt_loader.py: render_system_prompt 加防御注入
- (前一提交 7935cb6a 已包含 prompts.py/reviewer.py/viral_video.py 的合规改动)
2026-10-15 18:19:43 +08:00
xiaoxia 2d25e9989a fix(lipsync): 预合成模式补齐 script_text,修复 Ditto 任务 script_len=0 (#2312)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 13s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 20s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m8s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m16s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Failing after 4m10s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m26s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m55s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 5m28s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
fix(lipsync): 预合成模式补齐 script_text,修复 Ditto 任务 script_len=0 (#2312)
2026-10-15 18:11:21 +08:00
CI Bot ddfd38efcf style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 5s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 9s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 12s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Failing after 2m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
2026-10-15 10:10:57 +00:00
xiaoxia 7935cb6a25 fix(viral-video): #2312 文案生成防医疗合规风险+自动重试
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 0s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m6s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m19s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 19s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m50s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m34s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m23s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m40s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m21s
CI/CD Pipeline / Integration Tests (push) Successful in 4m37s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m28s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
问题:养生/理疗类门店(如御众堂)生成的文案含「老师帮你看看」「一搭手就知道」
「别急着贴膏药」「颈肩腰腿哪儿酸哪儿胀」等诊疗暗示/诊断话术/贬低正规医疗的
违规内容,在出片前审核阶段才被拦截,用户体验差。

修复(三道防线,生成时就规避):
1. 【Prompt 侧】GLOBAL_CONSTRAINTS 之前定义了但没注入 storyboard 模板——现在
   实际注入;同时增加第6-8条医疗红线(不得出现诊疗/疗效/诊断暗示/效果承诺)。
2. 【行业自适应】新增 HEALTH_INDUSTRY_KEYWORDS + HEALTH_INDUSTRY_REDLINES,
   命中养生/健康/理疗/按摩/中医/产后/御众堂等关键词时,向 system prompt
   额外注入8条行业红线(禁止诊疗暗示/诊断/疗效承诺/医疗术语/贬低正规医疗/
   问诊式话术),从源头引导 LLM 只写放松/舒服/松快/解乏等感受类词。
3. 【本地规则兜底】reviewer 新增 _MEDICAL_REDLINE_PATTERNS(9组正则),
   本地快速扫描:包治/根治/一X就好/特效神药/一搭手就知道/老师帮你看看/
   别急着贴膏药/疗程对症/哪儿酸哪儿胀问诊式话术等,命中即 error。
4. 【自动重试闭环】阶段2 generate-copy 在生成后立即跑 LLM 深度审核(之前
   只在阶段3 confirm-copy 才跑),不通过则把 error issues 作为反馈拼入
   下一轮 prompt 让 LLM 针对性修复,最多自动重试 2 次;成功直接放行给用户,
   失败保留当前文案让用户确认,阶段3仍会再跑一次审核兜底。
5. Review prompt v2→v3:显式加入医疗/养生红线维度(诊断暗示/疗效承诺/
   医疗术语/冒充医生/贬低正规医疗),审核颗粒度更细。
6. Storyboard 版本 v4→v5(对应 prompt 内容变更)。

文件:
- packages/application/viral_video/prompts.py: GLOBAL_CONSTRAINTS 扩写+注入;
  新增 HEALTH_INDUSTRY_REDLINES/HEALTH_INDUSTRY_KEYWORDS;review prompt v3;
  NEGATIVE_RULES 加医疗禁令;storyboard 注入 {industry_redlines} 占位符
- packages/application/viral_video/reviewer.py: 新增 _MEDICAL_REDLINE_PATTERNS
  9组医疗违规正则;_check_compliance 扫描医疗红线
- apps/worker/worker_app/tasks/viral_video.py: 引入新常量;
  _step_script_generation 新增 extra_compliance_feedback 参数;
  阶段2 run_viral_video_generate_copy 加入合规自动重试循环(最多2次)
2026-10-15 18:04:45 +08:00
xiaoxia df8d32391d fix(docker): #2311 worker镜像补COPY scripts目录,seed_preset_voice_samples可在容器内直接执行
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m14s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m19s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m7s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m46s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m36s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m43s
AI Code Review / AI Code Review (pull_request) Successful in 7m13s
CI/CD Pipeline / Integration Tests (push) Successful in 8m22s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 9m0s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 10m9s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m1s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m18s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m29s
CI/CD Pipeline / Unit Tests (push) Failing after 21m3s
CI/CD Pipeline / Validate - Security (push) Successful in 22m9s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 26m1s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
api.Dockerfile已有COPY scripts/,worker.Dockerfile漏了。
staging部署时通过docker cp手动将脚本注入容器验证功能正常,
补上后新环境部署即可直接在容器内执行python scripts/seed_preset_voice_samples.py。
2026-10-15 17:18:59 +08:00
16 changed files with 1369 additions and 114 deletions
@@ -0,0 +1,257 @@
"""#2312 storyboard v5 (GLOBAL_CONSTRAINTS+健康行业红线) + review v3 (医疗合规维度) — 保底插入版
问题:#2308三字段拆分、#2311音频重构、#2312合规修复都只更新了代码默认 prompts.py,
没有写 alembic 同步 viral_video_prompt_templates 表。但后台管理端
(/viral-prompt-templates)允许运营在线编辑模板,运营手改的内容不能被迁移覆盖。
策略(重要):
- 本迁移**不** deactivate 任何已有的 active 模板;运营配置的 v6 等高版本保持原样。
- 仅当某个 prompt_type 当前**没有**任何 is_active=true 的模板时(即空库/异常状态),
才把本次插入的 v5/v3 设为 is_active=true 作为保底。
- 已存在 active 模板时,本迁移插入的 v5/v3 以 is_active=false 存档,不影响线上。
- 合规底线不靠本迁移覆盖模板来生效,而是由 prompt_loader.render_system_prompt 的
防御性注入(代码侧自动追加 GLOBAL_CONSTRAINTS + 行业红线)兜底,这样:
① 运营未来在后台随便改模板都不会丢合规底线;
② 新库/空库拿到的保底模板本身就合规。
- 配套 reviewer.py 的本地医疗正则兜底 + 阶段 2 LLM 审核自动重试,形成三层防线。
Revision ID: 111_vv_compliance_prompts
Revises: 110_add_tone_to_viral_video_jobs
Create Date: 2026-10-15
"""
from sqlalchemy import text
from alembic import op
revision = "111_vv_compliance_prompts"
down_revision = "110"
branch_labels = None
depends_on = None
# ── v5 storyboard(编导级分镜 v3.2-合规增强版)────────────────────────────
V5_STORYBOARD_SYSTEM = (
"你是一名懂短视频的编导和口播文案高手。你会拿到图片的真实观察、营销目的和用户参数,"
'请一次性完成对营销意图的理解,并产出可直接拍摄/生成的分镜脚本。不要单独输出"意图解析",'
"意图要直接体现在台词和分镜里。\n\n"
"## 输出格式(XML,严格按结构输出,不要输出额外解释)\n"
"<script>\n"
" <copy_display_markdown><![CDATA[直接展示给用户看的成片文案,用 Markdown 写成流畅叙述]]></copy_display_markdown>\n"
" <clips>\n"
' <clip index="1">\n'
" <time_range>0-3秒</time_range>\n"
" <voiceover>这一镜的口播台词</voiceover>\n"
" <shot>景别、机位高度、焦段、光圈、运镜(6项摄影参数,简短,如『中近景平视,50mm f/1.8,缓慢推镜』)</shot>\n"
" <visual>画面主体、场景、光线、氛围(只写画面内容,不含景别/运镜参数,如『暖光木色门店,店员微笑递茶,背景虚化』)</visual>\n"
" <action_details>人物动作、表情、物品操作细节(真人出镜镜头必填,纯产品/空镜填空线『-』)</action_details>\n"
" <reference_image_index>0</reference_image_index>\n"
" </clip>\n"
" </clips>\n"
" <voiceover_script>把所有 clip 的voiceover 连成完整口播稿</voiceover_script>\n"
" <theme>一句话主题</theme>\n"
" <negative>【反套路化要求】\n"
'禁止使用"家人们谁懂啊""绝绝子""宝子们""家人们""太绝了""yyds"等烂大街网络词;\n'
'禁止"很近"等错别字,应使用"最近";\n'
"禁止固定模板化开头;语言要像真人朋友之间的分享,自然、具体、有信息量。\n"
"禁止医疗诊疗类词汇(治疗/治愈/根治/疗效/特效/药到病除/一用就好/对症/偏方/秘方/一搭手就知道/帮你看看等)。\n"
"禁止效果承诺(包治/根治/立刻见效/永不复发/一用就好等)。</negative>\n"
"</script>\n\n"
"【必须遵守的硬约束】\n"
'1. 不编造时间:不写"今年最新""2024 爆款"等会过时的时间表述。\n'
'2. 不承诺效果:不写"保证""一定""100%有效""包治百病"等绝对化用语,不写任何效果承诺。\n'
"3. 不编造价格、销量、认证、奖项:除非用户在文案中明确给出,否则一律不写。\n"
"4. 符合广告法及平台社区规范,不触碰医疗/养生/金融等敏感行业红线。\n"
"5. 只描述图片中真实可见的内容,看不到的不瞎猜。\n"
"6. 不出现医疗/诊疗/治疗/治愈/疗效/根治/对症/药效/偏方/秘方/药到病除/一用就好/立刻见效/特效/克星/急救/救星/神药/祖传/宫廷秘方/一贴灵/一抹就好等宣称诊疗或疗效的词汇。\n"
'7. 养生/按摩/理疗/推拿/养生馆/调理类门店文案:只写"放松""舒缓""缓解疲劳""舒服""松快""解乏""轻松""舒展""按完轻松多了"等感受类表达,严禁暗示治病、治病根、诊疗、根治、对症、疗效、专家诊断、老师一搭手就知道问题在哪等越界表述。\n'
'8. 不冒充医生/专家/老师做诊疗判断,不写"老师帮你看看""一搭手就知道""哪儿疼治哪儿""对症调理"等暗示诊断/治疗的表述。\n\n'
"{industry_redlines}\n\n"
"## 写作要求\n"
"1. 口播台词:像真人面对镜头说话,短句、口语化、有停顿有情绪,开头 3 秒给出钩子;不要书面腔,不要机械报参数。\n"
"2. <shot> 只写6项摄影参数(景别/机位高度/焦段/光圈/运镜),简短不超过20字;<visual> 写观众会看到的画面主体/场景/光线/氛围;<action_details> 写人物动作/表情/物品操作细节(真人出镜必填)。三字段各司其职,不要混写。\n"
'3. copy_display_markdown:直接展示给最终用户的文案,用 Markdown 写成自然、流畅、有感染力的成片文案,可用小标题与短句组织;不要做字段列表,不要出现"镜头一/台词:"这类制作说明。\n'
"4. 内容必须来自图片观察与用户给出的信息,不编造卖点、不夸大、不使用绝对化用语和虚假承诺。\n"
"5. reference_image_index 填本镜参考图片序号(从 0 开始),没有合适参考图填 -1。\n"
"6. 分镜数量与时长匹配总时长,节奏紧凑。\n"
"7. 【字数/镜头数/时间轴硬约束】:严格遵守 user_prompt 里给出的 {duration_constraint_text},宁少勿多。\n"
"8. 每个 clip 必须分配一个 reference_image_index(从 0 开始的图片序号),没有合适图片填 -1。\n"
"9. 必须严格按<marketing_purpose><target_audience><persona><viral_structure><language><industry>指定的参数写文案和分镜,不能忽略任何一项用户参数。\n"
'10. 禁止使用"很近"等错别字,统一使用"最近"。'
)
V5_STORYBOARD_USER = (
"<marketing_purpose>{marketing_purpose}</marketing_purpose>\n"
"<industry>{industry}</industry>\n"
"<image_analysis>\n{image_summary}\n</image_analysis>\n"
"<user_parameters>\n"
"<theme_hint>{theme_hint}</theme_hint>\n"
"<duration>{duration}秒</duration>\n"
"<aspect_ratio>{aspect_ratio}</aspect_ratio>\n"
"<tone>{tone}</tone>\n"
"<target_audience>{target_audience}</target_audience>\n"
"<persona>{persona_hint}</persona>\n"
"<viral_structure>{viral_structure_hint}</viral_structure>\n"
"<language>{language_hint}</language>\n"
"<extra_requirements>{extra_requirements}</extra_requirements>\n"
"</user_parameters>\n"
"{video_style_section}\n"
"<duration_constraints>\n{duration_constraint_text}\n</duration_constraints>\n"
"请严格按 XML 结构输出分镜脚本。"
)
V5_STORYBOARD_EXAMPLE = (
"<script>\n"
" <copy_display_markdown><![CDATA[# 在御众堂,把松弛的自己一点点找回来\n"
"产后妈妈最懂那种力不从心,推开门,暖光和一杯热茶先接住了你。\n"
"最近连抱娃都觉得腰发硬,过来躺一会儿,按完整个背都松了,带娃也有力气了。]]></copy_display_markdown>\n"
" <clips>\n"
' <clip index="1">\n'
" <time_range>0-4秒</time_range>\n"
" <voiceover>生完娃,是不是连照镜子的勇气都没了?</voiceover>\n"
" <shot>中近景平视,50mm f/2.0,缓慢推镜</shot>\n"
" <visual>暖光浴室镜前,妈妈略显疲惫地看向镜中自己,镜灯打在侧脸</visual>\n"
" <action_details>妈妈手扶洗手台,微微低头再抬眼看镜,眼眶微红</action_details>\n"
" <reference_image_index>0</reference_image_index>\n"
" </clip>\n"
' <clip index="2">\n'
" <time_range>4-10秒</time_range>\n"
" <voiceover>推开门,暖光和一杯热茶先接住了你。</voiceover>\n"
" <shot>中景平视,35mm f/2.8,镜头缓慢平移</shot>\n"
" <visual>门店前台暖光木色装修,茶水冒热气,背景柔和虚化</visual>\n"
" <action_details>店员微笑双手递上茶杯,妈妈伸手接过,指尖轻触杯沿</action_details>\n"
" <reference_image_index>1</reference_image_index>\n"
" </clip>\n"
' <clip index="3">\n'
" <time_range>10-15秒</time_range>\n"
" <voiceover>来御众堂躺一会儿,整个人都松了。</voiceover>\n"
" <shot>近景缓慢拉远至中景,85mm f/1.8,匀速后拉</shot>\n"
" <visual>护理床暖光打在妈妈侧脸,最后画面露出御众堂品牌LOGO</visual>\n"
" <action_details>妈妈闭眼放松,嘴角微微上扬,肩膀缓缓下沉</action_details>\n"
" <reference_image_index>2</reference_image_index>\n"
" </clip>\n"
" </clips>\n"
" <voiceover_script>生完娃,是不是连照镜子的勇气都没了?推开门,暖光和一杯热茶先接住了你。来御众堂躺一会儿,整个人都松了。</voiceover_script>\n"
" <theme>产后妈妈走进御众堂重拾状态</theme>\n"
' <negative>模糊、畸变、夸大疗效、绝对化用语、"很近"等错别字</negative>\n'
"</script>"
)
# ── v3 review(文案审核 v3-医疗合规加强版)─────────────────────────────────
V3_REVIEW_SYSTEM = (
"你是一名短视频广告合规审核与文案优化专家。请审核下面这段口播文案:\n"
"1) 广告法与平台合规(绝对化用语、虚假承诺、导流违规、套路烂梗词);\n"
'2) **医疗/养生/健康红线(重点审查)**:是否出现诊疗暗示("帮你看看""一搭手就知道""老师诊断""检查"等)、'
'疗效/治愈承诺("治好""根治""见效""一用就好""药到病除""特效""克星""永不复发"等)、'
'医疗术语("疗程""对症""膏药""针灸""中药""偏方""秘方""诊疗""治疗""就诊"等)、'
'冒充医生/专家/老师做诊断、贬低正规医疗("别贴膏药""别吃药""别去医院"等);\n'
'3) 养生/按摩/理疗/推拿/保健类文案是否用了纯感受类表达(放松/舒缓/舒服/松快/解乏/轻松),而不是"治病/根治/疗效"类表达;\n'
"4) 口播是否自然、口语化、无书面腔;\n"
'5) 是否有明显错别字(例如把"最近"写成"很近")。\n\n'
"只输出 XML,结构:\n"
"<review>\n"
" <passed>true 或 false</passed>\n"
" <issues>\n"
' <issue dimension="违规词/夸大承诺/错别字/其他" severity="error或warning">具体问题</issue>\n'
" </issues>\n"
"</review>\n"
"没有问题时 issues 留空、passed 为 true。不要输出 rewrite/rewrite_suggestion 字段。"
)
V3_REVIEW_USER = "<voiceover_script>\n{voiceover_script}\n</voiceover_script>\n\n请审核以上口播文案。"
V3_REVIEW_EXAMPLE = (
"<review>\n"
" <passed>false</passed>\n"
" <issues>\n"
' <issue dimension="夸大承诺" severity="error">使用绝对化用语"100%有效",违反广告法</issue>\n'
' <issue dimension="违规词" severity="warning">使用套路词"绝绝子"</issue>\n'
" </issues>\n"
"</review>"
)
def _has_active(conn, prompt_type: str) -> bool:
row = conn.execute(
text("SELECT COUNT(*) FROM viral_video_prompt_templates WHERE prompt_type = :pt AND is_active = true"),
{"pt": prompt_type},
).scalar()
return bool(row and row > 0)
def _version_exists(conn, prompt_type: str, version: int) -> bool:
row = conn.execute(
text("SELECT id FROM viral_video_prompt_templates WHERE prompt_type = :pt AND version = :v"),
{"pt": prompt_type, "v": version},
).fetchone()
return row is not None
def _insert(conn, prompt_type: str, version: int, name: str, sys_p: str, usr_p: str, ex_p: str, active: bool) -> None:
conn.execute(
text(
"INSERT INTO viral_video_prompt_templates (name, prompt_type, version, system_prompt, user_prompt_template, example_output, is_active)"
" VALUES (:name, :pt, :ver, :sys, :usr, :ex, :active)"
),
{"name": name, "pt": prompt_type, "ver": version, "sys": sys_p, "usr": usr_p, "ex": ex_p, "active": active},
)
def _next_version(conn, prompt_type: str, minimum: int) -> int:
mx = (
conn.execute(
text("SELECT COALESCE(MAX(version), 0) FROM viral_video_prompt_templates WHERE prompt_type = :pt"),
{"pt": prompt_type},
).scalar()
or 0
)
return max(minimum, int(mx) + 1)
def upgrade():
conn = op.get_bind()
# storyboard v5:如果同 version 已存在(前次失败重跑)就跳过
sb_ver = 5
if not _version_exists(conn, "storyboard", sb_ver):
sb_active = not _has_active(conn, "storyboard")
_insert(
conn,
"storyboard",
sb_ver,
"编导级分镜v3.2-合规增强版(#2312)",
V5_STORYBOARD_SYSTEM,
V5_STORYBOARD_USER,
V5_STORYBOARD_EXAMPLE,
active=sb_active,
)
# review v3
rv_ver = 3
if not _version_exists(conn, "review", rv_ver):
rv_active = not _has_active(conn, "review")
_insert(
conn,
"review",
rv_ver,
"文案审核v3-医疗合规加强版(#2312)",
V3_REVIEW_SYSTEM,
V3_REVIEW_USER,
V3_REVIEW_EXAMPLE,
active=rv_active,
)
# 注意:不 deactivate 任何已有模板。运营在后台编辑的高版本(如 v6)保持 active。
# 合规底线由 prompt_loader.render_system_prompt 的防御性注入兜底:
# 检测到模板缺"不承诺效果"指纹则自动追加 GLOBAL_CONSTRAINTS,
# 缺 {industry_redlines} 占位符则直接追加行业红线内容,
# 因此不管 active 模板是 v5/v6/未来 v7,都会被自动补上合规底线。
def downgrade():
conn = op.get_bind()
# 删除本次迁移插入的 v5/v3 行(按 name 精确匹配,不误删运营自定义)
conn.execute(
text("DELETE FROM viral_video_prompt_templates WHERE name LIKE :n AND version IN (5, 3)"),
{"n": "%#2312%"},
)
# 不改动其他任何版本的 is_active 状态,避免误恢复被运营手动停用的版本。
+125
View File
@@ -0,0 +1,125 @@
"""#2312 恢复运营v6模板为active + 存档#2312合规模板
背景:旧版 alembic 111(commit 7935cb6a)错误地 _deactivate_all() 了所有现有模板,
把运营在后台 /viral-prompt-templates 配置的 v6(编导级分镜 v6)is_active 改成了 false,
并把 #2312 合规版(storyboard version=5 / review version=3)设为 active,覆盖了运营配置。
本迁移(112)的任务:
1. storyboard 类型:恢复 v6 为 is_active=true,把 #2312 插入的 v5 和运营试配的 v7 设为 is_active=false
2. review 类型:找到运营配置的最高版本(不是我们 alembic 插的 v3),恢复其 is_active=true;
把我们 alembic 插入的 v3 设为 is_active=false
3. 全部操作加 IF EXISTS 防护,幂等可重入。
4. 防御注入兜底依然生效(prompt_loader 自动追加合规底线到任何 active 模板),
运营 v6 恢复后仍会被自动追加 GLOBAL_CONSTRAINTS + 行业红线,合规不丢。
Revision ID: 112_restore_v6_prompt
Revises: 111_vv_compliance_prompts
Create Date: 2026-10-15
"""
from sqlalchemy import text
from alembic import op
revision = "112_restore_v6_prompt"
down_revision = "111_vv_compliance_prompts"
branch_labels = None
depends_on = None
# 我们 alembic 111 插入的版本号(用于识别哪些是代码插入的保底版本)
_OUR_SB_VERSION = 5 # #2312 storyboard v5
_OUR_RV_VERSION = 3 # #2312 review v3
# 运营期望恢复为 active 的版本
_OPERATOR_SB_ACTIVE_VERSION = 6 # 编导级分镜 v6
# 运营在旧111之后可能试配过的合规版本(需要存档)
_OPERATOR_SB_ARCHIVE_VERSIONS = [7]
def _has_row(conn, prompt_type: str, version: int) -> bool:
row = conn.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type=:pt AND version=:v"),
{"pt": prompt_type, "v": version},
).fetchone()
return row is not None
def _set_active(conn, prompt_type: str, version: int, active: bool) -> int:
"""设置某个 (type, version) 的 is_active;返回受影响行数(0 表示该行不存在)。"""
res = conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=:a " "WHERE prompt_type=:pt AND version=:v"),
{"a": bool(active), "pt": prompt_type, "v": version},
)
return res.rowcount or 0
def _ensure_only_one_active(conn, prompt_type: str, active_version: int) -> None:
"""确保 prompt_type 类型下只有 active_version 一个是 is_active=true。
其他所有该类型模板统一设为 false。"""
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=false " "WHERE prompt_type=:pt AND version!=:av"),
{"pt": prompt_type, "av": active_version},
)
# 再确保目标行是 true(之前可能本来就是 false)
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=true " "WHERE prompt_type=:pt AND version=:av"),
{"pt": prompt_type, "av": active_version},
)
def upgrade():
conn = op.get_bind()
# ── 1. storyboard:恢复运营 v6 ──────────────────────────────────────
if _has_row(conn, "storyboard", _OPERATOR_SB_ACTIVE_VERSION):
_ensure_only_one_active(conn, "storyboard", _OPERATOR_SB_ACTIVE_VERSION)
# 额外保险:v5/v7 明确设为 false(_ensure_only_one_active 已做,再次确认)
for v in [_OUR_SB_VERSION] + _OPERATOR_SB_ARCHIVE_VERSIONS:
if _has_row(conn, "storyboard", v):
_set_active(conn, "storyboard", v, False)
else:
# 极端情况:v6 不存在(库没跑过旧111或者被删了),保持 #2312 v5 active 作为保底
# 不做任何变更,避免把一个能用的状态改坏
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=true " "WHERE prompt_type=:pt AND version=:v"),
{"pt": "storyboard", "v": _OUR_SB_VERSION},
)
# ── 2. review:恢复运营版本,存档我们的 v3 ──────────────────────────
# 找 review 类型下、不是我们插入的 v3 的最高版本号
op_row = conn.execute(
text("SELECT MAX(version) FROM viral_video_prompt_templates " "WHERE prompt_type=:pt AND version!=:ev"),
{"pt": "review", "ev": _OUR_RV_VERSION},
).fetchone()
op_max_ver = op_row[0] if op_row else None
if op_max_ver is not None and _has_row(conn, "review", int(op_max_ver)):
# 有运营版本,恢复它为 active,我们 v3 存档
_ensure_only_one_active(conn, "review", int(op_max_ver))
if _has_row(conn, "review", _OUR_RV_VERSION):
_set_active(conn, "review", _OUR_RV_VERSION, False)
else:
# 没有运营版本(空库/新库),保持我们 v3 作为保底 active
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=true " "WHERE prompt_type=:pt AND version=:v"),
{"pt": "review", "v": _OUR_RV_VERSION},
)
def downgrade():
"""downgrade 回滚到旧111跑完后的状态:我们的 v5/v3 为 active,其他全部 false。
注意:这会再次 deactivate 运营 v6,仅用于回滚测试场景,生产不要执行 downgrade。"""
conn = op.get_bind()
# storyboard
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=false WHERE prompt_type=:pt"),
{"pt": "storyboard"},
)
if _has_row(conn, "storyboard", _OUR_SB_VERSION):
_set_active(conn, "storyboard", _OUR_SB_VERSION, True)
# review
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active=false WHERE prompt_type=:pt"),
{"pt": "review"},
)
if _has_row(conn, "review", _OUR_RV_VERSION):
_set_active(conn, "review", _OUR_RV_VERSION, True)
File diff suppressed because one or more lines are too long
+6
View File
@@ -623,6 +623,12 @@ class LipsyncService:
# 预合成模式:script_text 可空(因为 timings 已自带句子文本),但仍建议传
if not isinstance(sentence_timings, list) or len(sentence_timings) == 0:
raise MediaKitError("预合成模式 sentence_timings 不能为空", code="InvalidInput")
# 文案为空时从 sentence_timings 拼接兜底(Ditto 情绪分析依赖 script_text;
# 前端 #1875 起预合成 payload 不带 script_text,导致 job.script_text 落库为空)
if not (script_text or "").strip():
script_text = "".join(
str(item.get("text") or "") for item in sentence_timings if isinstance(item, dict)
).strip()
# 0.5 lip_sync 计费预扣(全局 points 开关 + 功能开关均开才扣)
prepaid_credits = 0.0
@@ -255,6 +255,8 @@ const AiAvatarPage: React.FC = () => {
audio_url: state.ttsPreview.audioUrl!,
audio_duration: state.ttsPreview.duration,
sentence_timings: state.ttsPreview.sentenceTimings,
// 预合成也必须带文案:后端落库 job.script_text,Ditto 情绪分析依赖它
script_text: state.scriptText,
enable_video_loop: true,
}
} else {
+7 -3
View File
@@ -302,11 +302,15 @@ def _legacy_upload_to_oss(local_path: Path, storage_key: str) -> str | None:
return None
def upload_to_oss(local_path: Path | str, storage_key: str) -> str | None:
"""上传文件到 OSS,返回公网 URL。"""
def upload_to_oss(
local_path: Path | str,
storage_key: str,
extra_headers: dict | None = None,
) -> str | None:
"""上传文件到 OSS,返回公网 URL。extra_headers 可传 x-oss-object-acl 等自定义头。"""
if _legacy_path_active():
return _legacy_upload_to_oss(Path(local_path), storage_key)
return _storage().upload_file_smart(local_path, storage_key)
return _storage().upload_file_smart(local_path, storage_key, extra_headers=extra_headers)
def get_signed_download_url(storage_key_or_url: str, expires_seconds: int = 3600) -> str | None:
+457 -75
View File
@@ -50,7 +50,11 @@ from packages.application.viral_video.constants import (
)
from packages.application.viral_video.constants import get_expected_shot_count as _const_expected_shot_count
from packages.application.viral_video.param_guides import get_param_guide
from packages.application.viral_video.prompts import COMPLIANCE_BLACKLIST
from packages.application.viral_video.prompts import (
COMPLIANCE_BLACKLIST,
HEALTH_INDUSTRY_KEYWORDS,
HEALTH_INDUSTRY_REDLINES,
)
from packages.domain.viral_video import (
STAGE_LABELS,
ViralVideoComplianceError,
@@ -903,26 +907,64 @@ def _step_video_analysis(job: ViralVideoJob) -> dict | None:
# ── PR3 P2(h): 参数指导优先查 DB(viral_video_param_guides),代码默认值兜底 ──
# 代码默认值保证 DB 未 seed / DB 异常时不阻断流程
_DEFAULT_PERSONA_HINTS: dict[str, str] = {
"宝妈": "温柔贴心,多从带娃和家庭实用角度分享,语气亲切有共鸣",
"店主": "热情实在,像当面招呼客人,突出靠谱和实在优惠",
"专业顾问": "专业可信,讲清原理和效果,用事实打消顾虑",
"年轻达人": "活泼有网感,节奏轻快,金句和梗自然不尬",
"老板型IP": "以老板第一人称出镜,真诚接地气,像招呼街坊邻居一样分享,突出创业初心和靠谱",
"知识博主": "条理清晰、数据说话,干货密度高,语气专业但不枯燥",
"生活美学": "画面感强,注重氛围和质感描述,语速偏慢,文字有诗意",
"健身教练": "energetic、鼓励式口吻,强调动作要领和效果变化",
"美妆达人": "细腻讲质地和妆效,像闺蜜安利,语气亲切有感染力",
"美食博主": "色香味描述丰富,口语化带馋感,节奏轻快",
"穿搭博主": "讲搭配逻辑和场景适配,时尚但不高冷,像朋友建议",
"育儿师": "科学育儿角度,温柔坚定,给具体可操作的建议",
"宝妈": "像身边闺蜜聊带娃日常,不说教,多讲真实带娃小故事和踩坑经历,语气亲切自然",
"店主": "像街坊邻居拉家常,语气热情实在,多聊店里发生的真实小事和顾客趣事,不喊口号不夸自己",
"专业顾问": "像懂行的朋友说实话,用大白话讲清原理,不端架子不堆术语,偶尔自嘲更可信",
"年轻达人": "活泼有网感,节奏轻快,金句和梗自然不尬,像跟同龄人吐槽分享",
"老板型IP": "第一人称出镜,真诚接地气像招呼街坊,多聊开店遇到的人和事,不刻意讲创业故事卖情怀",
"知识博主": "把干货讲得像聊天,条理清楚但不端着,多用比喻和生活例子,别像上课",
"生活美学": "画面感强,注重氛围和质感描述,语速偏慢,文字有诗意,别像产品说明书",
"健身教练": "energetic、鼓励式口吻,像在健身房当面带你练,多喊动作少讲道理",
"美妆达人": "细腻讲质地和妆效,像闺蜜凑一起试色,语气真实有感染力,不闭眼吹",
"美食博主": "色香味描述丰富,口语化带馋感,像朋友拉你去吃好吃的",
"穿搭博主": "讲搭配逻辑和场景适配,时尚但不高冷,像闺蜜帮你挑衣服",
"育儿师": "像有经验的邻居大姐,温柔但有主见,给具体办法不说大道理",
"专家型IP": '以有经验的内行人身份出镜,语气沉稳像跟老顾客聊天,直接讲干货和行业内情,不使用"我干这行XX年了"这种自我介绍开场,用一个具体场景或反常识观点切入,像熟人行家说实在话,不夸大不端着,偶尔带点恨铁不成钢的真诚感',
"通用个人IP": "亲切自然像朋友聊天,真实不端着,有自己的态度和小脾气,偶尔自嘲,让人觉得真实有意思",
"顾问型IP": '像对面坐了个靠谱朋友帮你出主意,语气温和耐心,先聊你的处境再给建议,不说"听我的准没错"这种命令话',
"创始人IP": "第一人称出镜像跟朋友聊天,多聊为什么做这件事的真实原因(可能就是一个小契机),少喊使命情怀,真诚有温度别端着",
"创业者IP": "真实接地气,有冲劲也有狼狈,多聊踩过的坑和真实感悟,不灌鸡汤不装成功人士,顺便带出产品/服务",
"从业者经验派": '一线老师傅/老员工视角,语气朴实直白像工友聊天,直接讲内部干货和挑选窍门,不用"我干了X年"开场证明资历,用一个内行人才知道的细节或反常识点切入,话糙理不糙',
"避坑顾问型": '像替朋友操心的明白人,直接说容易踩雷的点,用反面案例警醒,语气是"我替你试过了"不是"你听我的",别吓唬人',
"知识科普型": '把知识点讲得像八卦一样有意思,多用比喻和生活例子,不端着上课,让观众觉得"原来这么回事"',
"测评种草型": '真实体验不吹不黑,优缺点都讲,像朋友安利好物不说假话,常用"我帮你们试了""说实话"这类真实表达',
# 保留旧版备用项(运营后台可能配置)
"养生专家": "像家里长辈叮嘱注意身体,语气温暖不唠叨,讲通俗养生常识和日常小方法,不说包治百病的话",
"医生IP": "专业但不吓人,用通俗比喻讲健康知识,严禁给出诊疗建议和疗效承诺",
}
_DEFAULT_VIRAL_STRUCTURE_HINTS: dict[str, str] = {
"反差破局+亮明观点+还原现状": "开头3秒用反差/痛点钩子抓注意力,中段亮出核心卖点或观点,结尾还原真实到店/使用场景引导行动",
# ── 前端19个爆款结构,全部一一对应 ──
"反差破局+亮明观点+还原现状": "开头3秒抛出强烈反差(常识vs真相/过去vs现在/别人vs我)制造'居然这样'的错愕感抓注意力;中段亮出你的核心观点/卖点/方法,用事实和道理把观点立住;结尾还原真实到店/使用场景,让用户看到改变后的样子,引导行动",
"痛点场景植入+给出通关秘籍": "开头直接把用户日常最头疼的真实场景演出来(不是抽象描述,是具体的画面和细节),让观众'啊就是这样';中段分析痛点根源,自然给出你的'通关秘籍'——具体的产品/服务/方法,讲清为什么它能解决;结尾给明确行动指引",
"反常识开场+扎心现状+制造焦虑": "开头3秒抛出反常识观点/数据('90%的人都做错了'、'你以为的XX其实在害你')打破认知;中段把用户正在经历的糟糕现状一条条扎心摆出来,让观众越看越慌;结尾点出不改变的后果+给出解决出路,但要合规不恐吓、不贩卖焦虑过度,落到正向改变",
"核心难题+化解焦虑+描绘愿景": "开头点出用户最核心的难题/心结(不是表面痛点,是背后的焦虑);中段给出化解焦虑的思路和你的产品/服务作为具体方案;结尾描绘解决之后的美好画面/生活状态,给人希望和向往",
"痛点前置+前后对比+给出期许": "开头直接把痛点/糟心状态摆上台面,不绕弯;中段用'之前vs之后'、'用了vs没用'的强烈对比展示改变,对比要具体到细节(画面/感受/数据);结尾给出对用户的期许和鼓励,引导迈出第一步",
"悬念拉满+揭露危害+明确目的": "开头3秒用一个悬念/疑问勾住('你知道你天天在用的XX有多可怕吗?'),持续留钩子不解;中段一层层揭露问题的真相和潜在危害(合规范围内客观陈述,不夸大不恐吓);结尾亮明做这条视频的目的(帮你避坑/给你方案),给出明确方向",
"情绪共鸣+勾起好奇+拔高价值": "三段式:开头3秒用一句戳心的话/一个真实痛点场景打情绪共鸣,让观众觉得'说的就是我';中段抛出反常识/有悬念的点勾起好奇心('你知道吗?其实不用花冤枉钱'、'很多人都搞错了'),自然引出产品/服务;结尾拔高价值(情感升华/身份认同/对自己好一点/给家人更好的),给观众一个温暖且有分量的行动理由,不要硬广",
"颠覆认知+现状拆解+赋予价值": "开头3秒颠覆用户的固有认知('其实你一直理解错了'、'真相跟你想的完全不一样');中段拆解现状/行业真相/错误做法背后的原因,层层剥茧让用户恍然大悟;结尾赋予新认知和新选择的价值,让用户觉得'今天学到了',顺势引产品",
"结果先行+消除顾虑+保留悬念": "开头3秒直接甩结果/效果/成绩单('30天瘦了10斤'、'这家店回头率95%'),用结果抓注意力;中段打消用户的主要顾虑(贵不贵?难不难?有没有副作用?会不会被骗?)用事实/案例/承诺回应;结尾留个悬念引导到店/私信/下单了解更多",
"真实困境+认知反转+传授秘籍": "开头还原一个普通人都会遇到的真实困境/窘境,让观众代入;中段来一个认知反转('原来问题根本不在XX,而在YY')打破固有思路;结尾传授真正有效的秘籍/方法,你的产品/服务作为秘籍的载体自然出现",
"反差事实+案例佐证+戳破真相": "开头用一个反差强烈的事实/数据引起好奇('同样的东西,有人花300有人花30');中段用真实案例/故事/对比做佐证,让事实自己说话;结尾戳破背后真相/行业潜规则/认知误区,建立你'说真话'的信任",
"预埋悬念+标杆案例+引出核心": "开头预埋一个悬念/伏笔('最后这个方法让我彻底服了');中段讲一个标杆案例/成功故事,细节拉满让人信服;结尾揭示开头悬念,引出你的核心产品/服务/方法",
"危机渲染+放大痛点+输出干货": "开头渲染一个潜在危机/风险场景(合规、客观,不制造恐慌);中段把痛点放大到用户不得不重视的程度(讲清为什么不能忽视);结尾立刻输出实用干货/解决方案,让用户看完能立刻行动",
"逆袭开场+成功诀窍+低价引流": "开头3秒讲一个逆袭/翻身/从糟到好的故事钩子('从快倒闭到排队两小时'、'从0到月入10万');中段提炼2-3个成功诀窍/关键动作,干货要实;结尾用低门槛体验/福利/引流品引导到店/下单",
"反常识观点+分析危害+描述现状": "开头抛出一个反常识观点('越是勤快护肤皮肤越差');中段分析为什么常识是错的、继续做会有什么危害(客观不恐吓);结尾描述正确做法后的理想状态,引产品",
"正反对比+解析原因+简易方法": "开头同时展示正确做法vs错误做法/好结果vs坏结果的对比画面;中段解析为什么会有这种差异,找到关键原因;结尾给出人人都能上手的简易方法/工具/产品",
"真实场景+内心刻画+共情引导+展望未来": "开头还原一个真实到让人心酸/温暖/共鸣的生活场景,画面感拉满;中段刻画人物内心活动('那一刻我突然明白...'、'她嘴上不说其实...')让观众共情;引导情绪到高点;结尾展望更好的未来/改变,引产品/服务",
"连续否定+代入感受+打破认知+精准戳痛": "开头3秒连续否定用户的常见做法/认知('别再XX了!别再YY了!千万别ZZ!');中段让观众代入错误做法带来的糟糕感受/后果,让其心有戚戚;然后打破认知给出真相;最后精准戳中最核心的那个痛,引解决方案",
"揭秘行业+类比施压+放大焦虑+精准锁客": "开头用'揭秘'、'内幕'、'行内人不会告诉你'勾住好奇心;中段用生活化类比让用户秒懂问题本质;适当放大不改变的后果焦虑(合规不恐吓);结尾精准锁定你的目标客户,给出只有你能解决的方案和立刻行动的理由",
# ── 新增短剧式/反套路爆款结构(#2312创意大改) ──
"短剧式冲突开场": "开头3秒直接是一个正在发生的生活小冲突——夫妻拌嘴、顾客质疑、当场抓包、老板训人,有对话有情绪有反应,绝不自我介绍。在对话拉扯中自然带出产品/服务(比如顾客嫌贵师傅怼回去、老婆抱怨老公偷偷去按摩),全程像看一小段短剧不是看广告,结尾来个反转或留悬念勾住继续看。至少两个角色对话,镜头在角色间切,不要旁白解说。",
"反套路反转": "前半段故意顺着观众熟悉的套路走(推销、说教、老套的痛点开场),让观众以为又是普通广告正准备划走,中段突然一个反转打破预期——比如顾客嫌贵师傅说'不值我给你二百'、以为是看病结果师傅掏出个按摩球自己先玩上了、你以为她要骂老公结果她掏出一张会员卡说'下次带我一起'。反转后用干货或真实小故事收,结尾轻CTA不要硬推。",
"悬念揭秘式": "开头3秒抛一个让人忍不住想知道后续的悬念钩子('昨天来个顾客进门就哭'、'你绝对猜不到这个肩膀硬了十年的大哥按完第一句说啥'、'昨天店里来了个奇葩'),不要解释不要自我介绍直接丢钩子。中段像讲故事一样还原当时场景——人物、对话、反应、细节,让观众像听八卦一样听进去。结尾揭秘答案,自然带出产品/服务,再留一个轻量互动钩子('你猜他咋说的?评论区告诉我')。全程像聊天讲八卦不像念广告。",
# ── 保留旧版5个备用(运营后台可能配置) ──
"痛点切入+方案展示+效果对比": "开头直击用户痛点场景,中间展示产品/服务解决方案,结尾用前后对比强化效果",
"故事引入+产品种草+行动引导": "用一个真实小故事/案例引入,自然过渡到产品种草,结尾明确引导用户下一步行动",
"场景展示+价值输出+信任背书": "开头展示使用场景让用户代入,中间输出核心价值主张,结尾用客户评价/数据等信任背书收尾",
"悬念开场+层层递进+高潮转化": "开头制造悬念引发好奇,内容层层推进保持张力,高潮处给出转化钩子",
"情感共鸣+痛点唤醒+价值升华": "开头用真实生活场景唤醒情绪共鸣,中段直击用户深层痛点,结尾用情感化价值升华收尾,让观众在情绪驱动下自然接受",
"热点结合+观点输出+引导互动": "开头借热点事件/话题切入,中段亮出犀利观点引发讨论,结尾用提问或号召引导互动评论",
}
@@ -967,23 +1009,38 @@ def _marketing_purpose_hint(mp: str) -> str:
if db_text:
return db_text if db_text.startswith("【") else f"【营销目的:{mp}】{db_text}"
# 情绪短片(单人情感共鸣,非多角色短剧)
if "情绪短片" in mp or "情感短片" in mp:
return f"【营销目的:{mp}】情感短片模式,以第一人称真情实感口播或单主角内心独白为主,像跟老朋友掏心窝子说话,不要像朗诵或念稿子,情绪层层递进(共鸣→好奇→升华),禁止多角色对话、禁止平淡第三人称旁白、禁止说明书式介绍,用具体小事和真实感受打动人,结尾落到温暖的情感价值上,不要硬推。"
# 短剧类(多角色对话)
if any(k in mp for k in ["对话短剧", "反转短剧", "悬念短剧", "情绪短片"]):
return f"【营销目的:{mp}】短剧模式,必须双/多角色对话格式,台词用'角色:xxx'格式,镜头在角色间切换,禁止第三人称旁白解说。"
# 口播类(第一人称对镜头说话)
if any(k in mp for k in ["对话短剧", "反转短剧", "悬念短剧", "剧情短片", "故事短剧"]):
return f"【营销目的:{mp}】短剧模式,必须双/多角色对话格式,台词用'角色:xxx'格式,镜头在角色间切换,禁止第三人称旁白解说,要像真实发生的小事不是演广告。"
# 口播/种草/引流类(第一人称对镜头说话,但不要像卖货)
if any(
k in mp
for k in ["口播带货", "促销转化", "功能演示", "痛点解决", "获客引流", "账号涨粉", "活动通知", "场景种草"]
for k in [
"口播带货",
"促销转化",
"功能演示",
"痛点解决",
"获客引流",
"账号涨粉",
"活动通知",
"场景种草",
"口播种草",
"产品种草",
"门店引流",
]
):
return f"【营销目的:{mp}】口播模式,第一人称对镜头说话,像真人出镜,有语气停顿和情绪,禁止第三人称旁白。"
return f"【营销目的:{mp}】口播模式,第一人称对镜头像跟朋友聊天,有语气停顿和真实情绪,禁止第三人称旁白。不要说'专业''靠谱''效果好'这种自夸的话,用真实小故事、生活场景、顾客反应侧面体现,不要直接说自己好。"
# 门店类(店主/探店博主出镜)
if any(k in mp for k in ["门店发现", "到店实录", "招牌体验", "同城团购"]):
return f"【营销目的:{mp}】门店模式,店主或探店博主出镜讲解+场景展示,第一人称或角色对白,禁止上帝视角旁白。"
return f"【营销目的:{mp}】门店模式,像带朋友逛店一样自然,聊店里发生的真实小事、顾客的真实反应、你自己的真实感受,不要像导游介绍景点,第一人称或角色对白,禁止上帝视角旁白。"
# 品牌类(主演出镜或角色对白)
if any(k in mp for k in ["品牌主张", "品牌故事", "生活方式", "创意概念"]):
return f"【营销目的:{mp}】品牌模式,主演出镜说话或角色对白,禁止上帝视角旁白,要有品牌调性和情感共鸣。"
if any(k in mp for k in ["品牌主张", "品牌故事", "生活方式", "创意概念", "品牌宣传"]):
return f"【营销目的:{mp}】品牌模式,用一个真实小故事或生活片段自然带出感觉,不要喊品牌口号、不要讲品牌理念、不要刻意塑造高大上形象,主演出镜说话或角色对白,禁止上帝视角旁白,让观众看完觉得'这人/这牌子有点意思'而不是'又在打广告'。"
# 未匹配的营销目的:通用 hint
return f"【营销目的:{mp}】按该营销目的的风格编排,优先第一人称或角色对话,避免上帝视角旁白。"
return f"【营销目的:{mp}】按该营销目的的风格编排,用真实小故事和生活场景切入,优先第一人称或角色对话像聊天,避免上帝视角旁白,不要自夸不要硬推。"
def _target_customer_hint(tc: str) -> str:
@@ -994,12 +1051,24 @@ def _target_customer_hint(tc: str) -> str:
db_text = _db_guide("target_customer", tc)
if db_text:
return db_text if db_text.startswith("【") else f"【目标客户:{tc}】{db_text}"
if any(k in tc for k in ["18-25", "年轻", "学生", "Z世代", "95后", "00后"]):
return f"【目标客户:{tc}】台词要活泼、有梗、节奏快,可用网络流行语。"
if any(k in tc for k in ["30-45", "中年", "家庭", "宝妈", "职场"]):
return f"【目标客户:{tc}】台词要实用、有共鸣,强调性价比和品质。"
if any(k in tc for k in ["50+", "老年", "退休", "银发"]):
return f"【目标客户:{tc}】台词要清晰、慢节奏,强调健康和实惠。"
if any(k in tc for k in ["小镇青年", "县城青年", "三四线青年", "下沉青年"]):
return f"【目标客户:{tc}】小镇/县城青年客群:用词接地气有网感但不装,聊真实生活(工作、恋爱、养家、朋友),强调性价比、面子、实在好用、'在咱这儿也能用上',节奏中等偏快,可以适当用家乡自豪感和小镇生活共鸣点"
if any(k in tc for k in ["小镇中老年", "县城中老年", "乡镇", "下沉市场", "三四线"]):
return f"【目标客户:{tc}】下沉市场中老年客群:语速慢、用词朴实接地气,像街坊邻居拉家常,少用网络词和书面语,强调实在、靠谱、不花冤枉钱、看得见的好处,抓住他们对健康、子女、面子、怕踩坑的心理,语气亲切像家里亲戚推荐。"
if any(k in tc for k in ["Z世代", "95后", "00后", "18-25", "学生", "年轻人"]):
return f"【目标客户:{tc}】年轻客群:台词活泼有梗、节奏快、不端着,可以用网络流行语、emoji感表达,讲真实感受不装,强调颜值、个性、出片、社交话题性、情绪价值,避免说教和老气横秋的广告腔"
if "精致妈妈" in tc or any(k in tc for k in ["宝妈", "年轻妈妈"]):
return f"【目标客户:{tc}】精致妈妈客群:语气温柔有共鸣,讲妈妈们最关心的点(孩子健康、家人饮食、自我成长、家庭品质、省时间省精力),从'当妈之后我才发现'切入,强调安全、省心、好用、孩子喜欢/家人认可,像闺蜜分享带娃好物"
if any(k in tc for k in ["新锐白领", "年轻白领", "职场新人"]):
return f"【目标客户:{tc}】新锐白领客群:语速中等偏快,讲效率、讲品质、讲调性,强调省时省力、高级感、职场形象、生活仪式感,打工人共鸣点(加班、通勤、犒劳自己),用词干净利落不啰嗦"
if any(k in tc for k in ["资深中产", "中产", "高净值", "新中产"]):
return f"【目标客户:{tc}】资深中产客群:语气从容有品位,不喊口号不打折促销,强调品质、格调、健康生活、身份认同、长期价值、稀缺感,用审美和生活方式打动,少提价格多提体验和圈层认同"
if any(k in tc for k in ["都市蓝领", "蓝领", "打工族", "工人"]):
return f"【目标客户:{tc}】都市蓝领/打工族客群:用词直白实在,强调实惠耐用、真材实料、性价比、解决实际问题,不搞虚的概念和花里胡哨的包装,像工友兄弟之间推荐靠谱东西,语气豪爽接地气"
if any(k in tc for k in ["都市银发", "50+", "退休", "银发", "城市老人"]):
return f"【目标客户:{tc}】都市银发客群:语速慢、咬字清晰,强调健康养生、安全放心、子女孝心、方便使用、老字号/品牌可信度,像子女贴心叮嘱一样温暖,避免复杂概念和洋名词"
if any(k in tc for k in ["老年", "退休"]):
return f"【目标客户:{tc}】台词要清晰、慢节奏,用词朴实,强调健康、实惠、放心。"
if any(k in tc for k in ["高端", "商务", "精英", "白领"]):
return f"【目标客户:{tc}】台词要专业、有格调,强调品质和身份。"
return f"【目标客户:{tc}】按该客群的语言习惯和关注点组织口播内容。"
@@ -1007,11 +1076,36 @@ def _target_customer_hint(tc: str) -> str:
def _language_hint(language: str) -> str:
"""根据 language 代码返回语言提示(DB 精确覆盖优先,代码默认兜底)。"""
lang = (language or "zh-CN").strip().lower()
db_text = _db_guide("language", lang)
raw_lang = (language or "").strip()
# 前端传全名("中文(普通话)"/"粤语")也支持
_lang_alias = {
"中文": "中文(普通话)",
"普通话": "中文(普通话)",
"chinese": "中文(普通话)",
"粤语": "粤语",
"广东话": "粤语",
"白话": "粤语",
"cantonese": "粤语",
"英文": "英语",
"english": "英语",
"日文": "日语",
"日本語": "日语",
"japanese": "日语",
"韩文": "韩语",
"한국어": "韩语",
"korean": "韩语",
}
lang = _lang_alias.get(raw_lang, raw_lang)
db_text = _db_guide("language", lang) or _db_guide("language", raw_lang)
if db_text:
return f"【语言:{lang}】{db_text}"
_defaults: dict[str, str] = {
"中文(普通话)": "使用标准普通话,口语化表达,自然口语,像日常说话",
"粤语": "使用标准粤语(广东话)口播,用词贴近港澳/广东日常口语,可加入'嘅/咗/嘞/喺/唔'等粤语助词,发音自然地道,不要用普通话直译粤语",
"英语": "使用英语(English),自然口语化表达",
"日语": "使用日本語(Japanese),自然で口语的な表現,丁寧すぎず親しみやすい",
"韩语": "使用한국어(Korean),자연스럽고 친근한 구어체 표현",
# 兼容旧代码值
"zh-cn": "使用标准普通话,口语化表达",
"zh-tw": "使用台湾腔中文,语气温柔亲切",
"zh-hk": "使用粤语风格中文表达",
@@ -1246,6 +1340,37 @@ def _split_visual_field(visual: str) -> tuple[str, str, str]:
return ",".join(cam_parts), ",".join(vis_parts), ",".join(act_parts)
_ACTION_PERSON_KEYWORDS = re.compile(
r"(?:人物|模特|主播|女生|男生|女士|男士|女孩|男孩|妈妈|店员|顾客|客人|老人|孩子|宝宝|主角|她|他|老师|医生|专家)"
)
_ACTION_GESTURE_VERBS = re.compile(
r"(?:微笑|点头|转头|转身|伸手|拿起|举起|展示|递出|指向|接过|抚摸|拥抱|握着|拿着|端着|捧着|看着|望向|注视|打量|端详|走进|走出|走近|靠近|退后|坐下|站起|走来|走去|走动|拿起|放下|推开|拉开|凑近|侧身|前倾|后仰|揉|按|摸|捏|搓|擦|拭|抿嘴|挑眉|眨眼|张嘴|闭目|流泪|皱眉|惊喜|惊讶|满意|点头微笑|竖起大拇指|比心|打招呼|挥手|递过来|展示给|介绍|推荐|讲解|试用|体验|品尝|试穿|喷|涂|抹|敷|喝|吃|闻)"
)
def _infer_action_from_visual(visual_text: str) -> str:
"""当visual里也没明确动作描述时,根据画面主体推断一个安全的默认动作。
策略:
- 有人物:默认"主角面向镜头自然微笑,适当手势配合讲解"
- 纯商品/场景:默认"镜头缓慢推进/环绕展示产品细节"
- 含动作动词片段:优先截取含动词的子句
"""
text = (visual_text or "").strip()
if not text:
return ""
# 先尝试在整段里找含动作动词的子句(按句号/分号/感叹号切)
clauses = [c.strip() for c in re.split(r"[。!?!?;;]", text) if c.strip()]
for cl in clauses:
if _ACTION_GESTURE_VERBS.search(cl) and len(cl) <= 40:
return cl
# 含人物关键词 → 人物口播类默认动作
if _ACTION_PERSON_KEYWORDS.search(text):
return "主角面向镜头自然出镜,配合手势和表情进行口播讲解"
# 纯产品/场景
return "镜头缓慢推进,清晰展示产品/场景细节"
def _parse_script_xml(
xml_body: str,
raw_full: str,
@@ -1264,19 +1389,60 @@ def _parse_script_xml(
display_md = xp.text_of(xml_body, "copy_display_markdown")
clips = xp.find_all(xml_body, "clip")
# #2312: 兼容 v4/v5/v6 多种模板输出格式——每个字段尝试多个标签别名
# 运营后台的 v6 模板可能用中文标签(镜头/画面/动作/台词)或英文别名(scene/camera/dialogue)
_CLIP_TAGS = ("clip", "镜头", "shot_item", "scene", "segment")
clips: list[dict] = []
for _ct in _CLIP_TAGS:
clips = xp.find_all(xml_body, _ct)
if clips:
break
# 额外兜底:<clips> 直接子项的情况已被 find_all 覆盖
shots: list[dict] = []
voice_parts: list[str] = []
for i, c in enumerate(clips):
a = c.get("attrs", {})
body = c.get("text", "") or ""
voice = xp.text_of(body, "voiceover") or xp.text_of(body, "voice_text")
# #2308: 优先读新 <shot>(纯6项摄影参数),fallback 到 <visual>(旧schema混写)
shot_meta = xp.text_of(body, "shot") or ""
visual_full = xp.text_of(body, "visual") or xp.text_of(body, "shot_type_angle_movement") or ""
action_raw = xp.text_of(body, "action_details") or ""
# 台词/口播别名
voice = (
xp.text_of(body, "voiceover")
or xp.text_of(body, "voice_text")
or xp.text_of(body, "dialogue")
or xp.text_of(body, "台词")
or xp.text_of(body, "口播")
or xp.text_of(body, "对白")
or xp.text_of(body, "narration")
)
# 景别/运镜别名
shot_meta = (
xp.text_of(body, "shot")
or xp.text_of(body, "camera")
or xp.text_of(body, "景别")
or xp.text_of(body, "运镜")
or xp.text_of(body, "shot_type")
or ""
)
# 画面描述别名(含旧字段 shot_type_angle_movement 兜底)
visual_full = (
xp.text_of(body, "visual")
or xp.text_of(body, "画面")
or xp.text_of(body, "scene_description")
or xp.text_of(body, "description")
or xp.text_of(body, "场景")
or xp.text_of(body, "shot_type_angle_movement")
or ""
)
# 动作细节别名
action_raw = (
xp.text_of(body, "action_details")
or xp.text_of(body, "action")
or xp.text_of(body, "动作")
or xp.text_of(body, "动作细节")
or xp.text_of(body, "人物动作")
or ""
)
if shot_meta:
# 新schema:<shot>是摄影参数,<visual>是纯画面描述,<action_details>是动作细节
# 新schema:<shot>是摄影参数,<visual>是画面描述,<action_details>是动作细节
cam_text = shot_meta.strip()
visual_text = visual_full.strip()
action_text = (action_raw or "").strip()
@@ -1287,15 +1453,44 @@ def _parse_script_xml(
cam_text, visual_text, action_text = _split_visual_field(visual_full)
if not action_text and action_raw:
action_text = action_raw.strip()
ref_raw = xp.text_of(body, "reference_image_index")
# #2312 E2E遗留: v6运营模板把动作嵌在visual/画面字段里没输出独立动作标签。
# 若action仍为空但visual有内容,从visual文本中智能拆分提取动作片段
if not action_text and visual_text:
_, _vis_only, _act_extracted = _split_visual_field(visual_text)
if _act_extracted:
action_text = _act_extracted
visual_text = _vis_only # 拆分后的纯画面替换原visual
# 最终兜底:若visual里也拆不出动作,根据画面生成一个安全默认动作描述
if not action_text and visual_text:
action_text = _infer_action_from_visual(visual_text)
# 若cam_text为空,从visual里兜底拆
if not cam_text and visual_text:
_cam_extracted, _vis2, _ = _split_visual_field(visual_text if visual_text != visual_full else visual_full)
if _cam_extracted:
cam_text = _cam_extracted
if not visual_text or visual_text == visual_full:
visual_text = _vis2
# 参考图别名
ref_raw = (
xp.text_of(body, "reference_image_index")
or xp.text_of(body, "ref_image")
or xp.text_of(body, "参考图")
or xp.text_of(body, "image_index")
)
ref_idx = xp.attr_int(ref_raw, -1) if ref_raw not in (None, "") else -1
if not isinstance(ref_idx, int) or ref_idx < 0:
ref_idx = None
speaker = xp.text_of(body, "speaker") or "主播"
# speaker别名 + 时间范围别名
speaker = xp.text_of(body, "speaker") or xp.text_of(body, "speaker_name") or xp.text_of(body, "角色") or "主播"
if voice:
voice_parts.append(f"[speaker:{speaker}]{voice}")
shot = {
"time_range": a.get("time_range") or xp.text_of(body, "time_range") or f"{i * 3}-{(i + 1) * 3}秒",
"time_range": a.get("time_range")
or a.get("time")
or xp.text_of(body, "time_range")
or xp.text_of(body, "time")
or xp.text_of(body, "时长")
or f"{i * 3}-{(i + 1) * 3}秒",
# shot_type_angle_movement:纯6项摄影参数,不塞画面动作
"shot_type_angle_movement": cam_text or "中景平视,固定镜头",
# scene_and_dialogue:纯口播对白(不再拼接visual,避免重复)
@@ -1303,8 +1498,13 @@ def _parse_script_xml(
# 画面描述(拆出来的纯画面)放到 shot 里供视频prompt使用
"visual": visual_text,
"action_details": action_text,
"audio_bgm": xp.text_of(body, "audio_bgm") or "轻快BGM",
"transition": xp.text_of(body, "transition") or ("硬切" if i < len(clips) - 1 else "结束"),
"audio_bgm": xp.text_of(body, "audio_bgm")
or xp.text_of(body, "bgm")
or xp.text_of(body, "音效")
or "轻快BGM",
"transition": xp.text_of(body, "transition")
or xp.text_of(body, "转场")
or ("硬切" if i < len(clips) - 1 else "结束"),
"reference_image_index": ref_idx,
"voiceover": voice or "",
}
@@ -1506,6 +1706,7 @@ def _step_script_generation(
job: ViralVideoJob,
image_analysis: dict,
on_delta: Optional[Callable[[str, str], None]] = None,
extra_compliance_feedback: str = "",
) -> dict:
"""步骤: 意图理解 + 分镜生成一次完成(单一重试 for 循环 + 双格式解析)。
@@ -1596,6 +1797,36 @@ def _step_script_generation(
# 字数/镜头数约束(统一由 constants 生成,注入到 prompt 占位符 {duration_constraint_text})
_duration_constraint_text = build_duration_constraint_text(dur)
# #2312: 根据行业自动注入合规红线(健康/养生/理疗/按摩/中医等)
_industry_redlines_text = ""
_industry_blob = " ".join(
[
str(industry or ""),
str(marketing_purpose or ""),
str(theme_hint or ""),
str(getattr(job, "name", "") or ""),
]
)
if any(kw in _industry_blob for kw in HEALTH_INDUSTRY_KEYWORDS):
_industry_redlines_text = HEALTH_INDUSTRY_REDLINES
# 重试时携带上次审核失败的具体问题,让 LLM 针对性修复
if extra_compliance_feedback:
if _industry_redlines_text:
_industry_redlines_text = (
_industry_redlines_text
+ "\n\n【上次生成审核未通过的具体问题(必须修复)】\n"
+ extra_compliance_feedback
)
else:
_industry_redlines_text = "【上次生成审核未通过的具体问题(必须修复)】\n" + extra_compliance_feedback
# 非健康行业也可能混入医疗承诺,统一追加一段通用提醒
if not _industry_redlines_text and not extra_compliance_feedback:
_industry_redlines_text = "(非医疗健康行业,遵守通用广告法:不使用绝对化用语、不做效果承诺)"
elif not _industry_redlines_text:
_industry_redlines_text = (
"【通用合规】遵守广告法,不使用绝对化用语,不做效果承诺。\n" + extra_compliance_feedback
)
llm_messages = build_messages(
template,
marketing_purpose=marketing_purpose or "未指定",
@@ -1615,6 +1846,7 @@ def _step_script_generation(
extra_requirements=extra_req,
video_style_section=style_section,
duration_constraint_text=_duration_constraint_text,
industry_redlines=_industry_redlines_text,
)
# primary 模型(DB 配置的首选,豆包 Seed 2.1 Pro,稳但稍慢)
@@ -1773,7 +2005,7 @@ def _resolve_tts_voice_id(job: ViralVideoJob) -> str:
if not raw_voice_id:
return default_voice
# 克隆音色:前端传 profile.id,需查 DB 取 cosyvoice_voice_id
# 克隆音色:前端可能传 profile.id(UUID) 或 cosyvoice voice_id,先按UUID查再按voice_id兜底
if voice_source in ("my_voice", "clone"):
session = None
try:
@@ -1783,7 +2015,13 @@ def _resolve_tts_voice_id(job: ViralVideoJob) -> str:
session = SessionLocal()
_repo = SQLAlchemyVoiceCloneProfileRepository(session)
# #2312:前端选克隆音色时可能传 cosyvoice voice_id(非UUID),get()查不到时用find_by_voice_id兜底
_profile = _repo.get(raw_voice_id)
if not _profile:
try:
_profile = _repo.find_by_voice_id(raw_voice_id)
except Exception:
_profile = None
if _profile and _profile.status.value == "ready" and (_profile.voice_id or "").strip():
logger.info(
"[爆款视频] 克隆音色解析: profile_id=%s → cosyvoice_voice_id=%s",
@@ -1874,12 +2112,13 @@ _PRESET_VOICE_SAMPLE_OSS_KEY_FMT = "static/voice-samples/preset/{voice_id}_sampl
# #2311: 克隆音色预处理样本 OSS 路径(首次出片时用原音频ffmpeg截8s上传,后续永久复用)
_CLONE_VOICE_SAMPLE_OSS_KEY_FMT = "static/voice-samples/clone/{profile_id}_sample.mp3"
# #2311: 样本目标时长(秒)
_VOICE_SAMPLE_TARGET_SECS = 8
_VOICE_SAMPLE_TARGET_SECS = 10 # #2312 Wan官方建议≥10s音色参考更稳
def _trim_audio_to_sample(local_path: Path, target_secs: int = _VOICE_SAMPLE_TARGET_SECS) -> Path | None:
"""#2311: 用ffmpeg把音频裁剪/标准化为target_secs秒的单声道16kHz参考样本。
取音频中段(避开开头呼吸/结尾尾音/可能的静音段),输出到临时目录mp3。
"""#2311+#2312: 用ffmpeg把音频裁剪/标准化为target_secs秒的参考样本。
取音频中段(避开开头呼吸/结尾尾音/可能的静音段),输出mp3。
#2312升级:精确seek(-ss在-i后)+24kHz+128kbps+首尾50ms淡入淡出防切音,音色还原更准。
失败返回None。
"""
import subprocess
@@ -1907,24 +2146,35 @@ def _trim_audio_to_sample(local_path: Path, target_secs: int = _VOICE_SAMPLE_TAR
if dur <= 0:
return None
# 取中段;若比目标短则从头取
start = max(0.0, (dur - target_secs) / 2.0) if dur > target_secs + 1 else 0.0
if dur > target_secs + 1:
start = max(0.0, (dur - target_secs) / 2.0)
else:
start = 0.0
out_dir = Path(tempfile.mkdtemp(prefix="vv_voice_sample_"))
out = out_dir / "sample.mp3"
# #2312: -ss 放 -i 后做精确seek(避免关键帧偏移导致截点不准);
# 24kHz采样率+128kbps单声道(Wan音色特征提取对高频信息敏感,16k/96k偏低);
# afade做首尾50ms淡入淡出防止硬切产生爆音
fade_in = 0.05
fade_out_start = max(0.0, target_secs - 0.05)
af = f"afade=t=in:st=0:d={fade_in},afade=t=out:st={fade_out_start:.2f}:d=0.05"
cmd = [
"ffmpeg",
"-y",
"-i",
str(local_path),
"-ss",
f"{start:.2f}",
"-t",
str(target_secs),
"-i",
str(local_path),
"-ac",
"1",
"-ar",
"16000",
"24000",
"-b:a",
"96k",
"128k",
"-af",
af,
str(out),
]
subprocess.run(cmd, capture_output=True, timeout=30, check=True)
@@ -1982,20 +2232,35 @@ def _resolve_voice_sample_audio(job: ViralVideoJob) -> str | None:
return _tts_voice_sample_fallback(job)
# --- 预置音色:直接读预生成sample_audio_url ---
if voice_source not in ("my_voice", "clone"):
# #2312 防御:前端可能漏传 voice_source(空串),先按预置查;查不到再尝试克隆路径
_is_clone_source = voice_source in ("my_voice", "clone")
if not _is_clone_source:
from packages.domain.preset_voices import get_preset_voice_by_id
preset = get_preset_voice_by_id(raw_voice_id)
sample_url = (preset.sample_audio_url if preset else "").strip()
if not sample_url:
# 部署脚本没跑/未回填:警告+兜底TTS,保证不崩
if sample_url:
logger.info(
"[爆款视频][音色样本] 命中预置静态样本: %s (voice_source=%s)", raw_voice_id, voice_source or "empty"
)
return sample_url
# 预置查不到:如果 voice_source 暗示为预置("preset"/空串等),降级TTS
# 但如果 voice_id 看起来像 UUID(克隆profile id),继续走克隆路径
import re as _re
_is_uuid_like = bool(_re.match(r"^[0-9a-f]{8}-[0-9a-f]{4}-", raw_voice_id, _re.I))
if voice_source in ("preset", "") and not _is_uuid_like:
logger.warning(
"[爆款视频][音色样本] 预置音色 %s 无sample_audio_url(seed_preset_voice_samples未跑?),降级TTS",
raw_voice_id,
)
return _tts_voice_sample_fallback(job)
logger.info("[爆款视频][音色样本] 命中预置静态样本: %s", raw_voice_id)
return sample_url
# 否则(UUID-lik或其他未知source)继续走克隆路径兜底
logger.info(
"[爆款视频][音色样本] voice_source=%s 预置查不到,尝试克隆路径兜底 voice_id=%s",
voice_source or "empty",
raw_voice_id[:40],
)
# --- 克隆音色:原音频ffmpeg预处理+OSS缓存 ---
profile_id = raw_voice_id
@@ -2023,10 +2288,36 @@ def _resolve_voice_sample_audio(job: ViralVideoJob) -> str | None:
session = SessionLocal()
_repo = SQLAlchemyVoiceCloneProfileRepository(session)
# #2312 关键修复:前端在选克隆音色时,voice_id传的可能是 CosyVoice voice_id
# (形如 cosyvoice_xxx),也可能是 profile 主键 UUID。先按主键 UUID get(),
# 查不到再按 voice_id 字段回退查找,避免误降级TTS。
_profile = _repo.get(profile_id)
if not _profile or not _profile.is_ready:
logger.warning("[爆款视频][音色样本] 克隆profile %s 不存在/未就绪,降级TTS", profile_id)
if not _profile:
try:
_profile = _repo.find_by_voice_id(profile_id)
except Exception as _e:
logger.warning("[爆款视频][音色样本] find_by_voice_id异常: %s", _e)
if not _profile:
logger.error(
"[爆款视频][音色样本] 克隆profile查找失败 profile_id/voice_id=%s 降级TTS(用户将听不到本人音色)",
profile_id,
)
return _tts_voice_sample_fallback(job)
if not _profile.is_ready:
logger.warning(
"[爆款视频][音色样本] 克隆profile %s(id=%s,voice_id=%s) 状态未就绪 status=%s,降级TTS",
getattr(_profile, "name", ""),
_profile.id,
getattr(_profile, "voice_id", ""),
getattr(_profile, "status", ""),
)
return _tts_voice_sample_fallback(job)
logger.info(
"[爆款视频][音色样本] 克隆profile命中: name=%s id=%s voice_id=%s",
getattr(_profile, "name", ""),
_profile.id,
getattr(_profile, "voice_id", ""),
)
# 优先走source_asset_id拿永久storage_key重签下载
source_asset_id = (_profile.metadata or {}).get("source_asset_id", "")
if source_asset_id:
@@ -2065,11 +2356,15 @@ def _resolve_voice_sample_audio(job: ViralVideoJob) -> str | None:
logger.warning("[爆款视频][音色样本] ffmpeg预处理失败,降级TTS profile=%s", profile_id)
return _tts_voice_sample_fallback(job)
# 上传OSS永久缓存
# 上传OSS永久缓存(#2312 E2E问题3: 必须public-read,Wan/Seedance API才能拉到)
try:
url = upload_to_oss(sample_path, oss_key)
url = upload_to_oss(
sample_path,
oss_key,
extra_headers={"x-oss-object-acl": "public-read"},
)
if url:
logger.info("[爆款视频][音色样本] 克隆样本已缓存OSS: %s", profile_id)
logger.info("[爆款视频][音色样本] 克隆样本已缓存OSS(public-read): %s", profile_id)
return url
except Exception as e:
logger.warning("[爆款视频][音色样本] 克隆样本上传OSS失败: %s", e)
@@ -2495,7 +2790,16 @@ def _assemble_seedance_prompt(copy_result: dict, job: ViralVideoJob, has_voice_r
if provider == "dashscope":
# ========== Wan 3.0 格式 ==========
head = f"{theme},{style_text or _WAN_HEAD_SCENE_FALLBACK},总时长{total_duration}秒。"
# #2312 双保险:文字层明确画幅要求,避免API参数偶发被忽略时出横屏
_ar_hint = {
"9:16": "竖屏构图(9:16手机竖屏观看,人物居中竖幅取景)",
"16:9": "横屏构图(16:9宽银幕取景)",
"1:1": "正方形构图(1:1居中取景)",
"3:4": "竖幅构图(3:4竖屏取景)",
"4:3": "横幅构图(4:3取景)",
"21:9": "超宽银幕构图(21:9电影宽幅)",
}.get(aspect_ratio, f"画幅{aspect_ratio}")
head = f"{theme},{style_text or _WAN_HEAD_SCENE_FALLBACK},{_ar_hint},总时长{total_duration}秒。"
body: list[str] = [head, ""]
# #2311 短音色样本:加音色提取指令
if has_voice_ref:
@@ -2639,7 +2943,22 @@ def _step_render(job: ViralVideoJob, copy_result: dict, tts_audio_url: str | Non
len(ref_videos),
tmpdir,
)
logger.info("[爆款视频] Seedance prompt (前300字): %s", prompt[:300])
# #2312 关键链路日志:明确打印音色URL和来源,便于排查克隆音色失效
if ref_audios:
_va0 = ref_audios[0] or ""
logger.info(
"[爆款视频] 音色参考URL(前120字) voice_id=%s voice_source=%s url=%s",
(getattr(job, "voice_id", "") or "")[:40],
(getattr(job, "voice_source", "") or "") or "preset",
_va0[:120],
)
else:
logger.info(
"[爆款视频] 无音色参考(原生音频) voice_id=%s voice_source=%s",
(getattr(job, "voice_id", "") or "")[:40],
(getattr(job, "voice_source", "") or "") or "preset",
)
logger.info("[爆款视频] 视频prompt (前500字): %s", prompt[:500])
# #2172/#2220: 使用信任链预热结果(阶段1后台 Seedream t2i 并行),不可用时现场补跑
pre_trusted = None
@@ -3007,19 +3326,82 @@ def run_viral_video_generate_copy(self: Task, job, repo, session) -> dict:
event_type="viral_video:script_delta",
)
copy_result = _step_script_generation(job, image_analysis, on_delta=_on_script_delta)
_emit_progress(
job_id,
ViralVideoStage.SCRIPT_GENERATION,
85.0,
"分镜脚本生成完成",
{"shots": len(copy_result.get("shots", []))},
)
# #2312: 合规自动重试——生成后立即做 LLM 深度审核,不通过则把违规点反馈给 LLM 重新生成(最多 2 次)
# 目标:在用户看到文案之前就把违规问题消化掉,避免用户点"生成视频"才在阶段3被卡
_MAX_COMPLIANCE_RETRY = 2
copy_result = None
_compliance_feedback = ""
for _retry_i in range(_MAX_COMPLIANCE_RETRY + 1):
copy_result = _step_script_generation(
job,
image_analysis,
on_delta=_on_script_delta if _retry_i == 0 else None,
extra_compliance_feedback=_compliance_feedback,
)
_emit_progress(
job_id,
ViralVideoStage.SCRIPT_GENERATION,
85.0,
f"分镜脚本生成{'(合规修复重试中...)' if _retry_i > 0 else '完成'}",
{"shots": len(copy_result.get("shots", []))},
)
# 快速黑名单本地替换(绝对化用语、套路词等)
_set_stage(job, repo, session, ViralVideoStage.REVIEW, "正在快速检查脚本合规性...")
voiceover = (copy_result or {}).get("voiceover_script", "") or ""
_quick_compliance_blacklist_check(copy_result)
# LLM 深度审核(阶段2也跑,失败不阻塞;发现 error 级问题则反馈给 LLM 重试)
try:
from packages.application.viral_video.reviewer import Reviewer
_reviewer = Reviewer()
_rev_res = _reviewer.review((copy_result or {}).get("voiceover_script", "") or "")
if _rev_res.passed or not [i for i in _rev_res.issues if i.severity == "error"]:
logger.info(
"[爆款视频][阶段2] 脚本合规审核通过 job_id=%s attempt=%d issues=%d",
job_id,
_retry_i + 1,
len(_rev_res.issues),
)
break
# 有 error 级问题——拼反馈文本让 LLM 下一轮针对性改
_err_issues = [i for i in _rev_res.issues if i.severity == "error"]
_compliance_feedback = (
f"上次生成的文案存在以下 {len(_err_issues)} 个合规问题,请全部修复后重新生成文案和分镜,"
f"严格遵守系统里的合规红线,不要再犯:\n"
+ "\n".join(f"- [{i.dimension}] {i.text}" for i in _err_issues[:8])
)
logger.warning(
"[爆款视频][阶段2] 合规审核未通过 attempt=%d/%d job_id=%s issues=%s",
_retry_i + 1,
_MAX_COMPLIANCE_RETRY + 1,
job_id,
[i.text[:40] for i in _err_issues[:3]],
)
if _retry_i >= _MAX_COMPLIANCE_RETRY:
# 最后一次仍不通过,交给阶段3兜底(可能是 LLM reviewer 误判;阶段3仍会跑一次)
logger.warning(
"[爆款视频][阶段2] 合规自动重试达到上限,保留当前脚本交给用户确认 job_id=%s",
job_id,
)
break
# 清回调,避免重试时重复推 stream 事件把前端搞乱
_on_script_delta = None
_script_stage_start = time.time()
_set_stage(
job,
repo,
session,
ViralVideoStage.SCRIPT_GENERATION,
f"文案合规检测发现问题,正在自动修复(第{_retry_i+1}次重试)...",
)
continue
except Exception as _e:
logger.warning("[爆款视频][阶段2] 合规预审核异常,跳过自动重试: %s", _e)
break
# 合规审核后置:快速黑名单检查;LLM 深度审核放到 confirm-copy 出片前
_set_stage(job, repo, session, ViralVideoStage.REVIEW, "正在快速检查脚本合规性...")
voiceover = (copy_result or {}).get("voiceover_script", "") or ""
_quick_compliance_blacklist_check(copy_result)
_emit_progress(job_id, ViralVideoStage.REVIEW, 95.0, "脚本合规初检完成")
job.mark_copy_generated(copy_result)
+2
View File
@@ -37,6 +37,8 @@ COPY alembic.ini /app/alembic.ini
COPY alembic/ /app/alembic/
COPY migrations/ /app/migrations/
COPY packages/ /app/packages/
# #2311: 预置音色样本 seed 脚本等运维/部署脚本需在容器内可用
COPY scripts/ /app/scripts/
# PR #1844 起,worker 还需要加载 apps.api.app.tasks.lipsync_tts,
# 该 task 依赖 app.services.* 与 app.core.celery_app(PYTHONPATH=/app/apps/api 下解析)。
# 为避免后续新增 task 再次漏 COPY,直接把整个 apps/api/app/ 复制进 worker 镜像。
@@ -155,16 +155,32 @@ def get_template(prompt_type: str, *, force_refresh: bool = False) -> Optional[P
if not force_refresh and cached and now - cached[0] < CACHE_TTL_SECONDS:
return cached[1]
template = _load_from_db(prompt_type) or _fallback(prompt_type)
template = _load_from_db(prompt_type)
_from = "db"
if template is None:
template = _fallback(prompt_type)
_from = "code-default"
if template is None:
_warn_once(
f"no_template:{prompt_type}",
f"NO TEMPLATE for {prompt_type} (neither db nor code defaults)",
"no template in db or code defaults",
)
if template is not None:
with _lock:
_cache[prompt_type] = (now, template)
return None
# #2312 实证日志:每次缓存刷新都打印实际加载的模板来源/版本/名称/sp前100字,
# 便于确认后台运营改动是否真的生效(30秒TTL缓存刷新时会打)
_sp_preview = (template.system_prompt or "").replace(chr(10), " ")[:100]
logger.info(
"[prompt_loader] 加载模板 type=%s 来源=%s version=%d name=%s is_active=%s sp_preview=%r",
prompt_type,
_from,
template.version,
template.name,
template.is_active,
_sp_preview,
)
with _lock:
_cache[prompt_type] = (now, template)
return template
@@ -248,8 +264,53 @@ def _safe_format(text: str, kwargs: dict) -> str:
def render_system_prompt(template: PromptTemplate, **kwargs) -> str:
"""system_prompt 含运行时变量时填充;example_output 存在时作为 few-shot 样例追加到末尾。"""
"""system_prompt 含运行时变量时填充;example_output 存在时作为 few-shot 样例追加到末尾。
#2312 防御:DB 配置的模板(viral_video_prompt_templates)若漏掉 GLOBAL_CONSTRAINTS 或
# industry_redlines 占位符,代码侧兜底追加,避免再次出现"代码加了规则但 DB 旧模板没带"
# 的静默失效问题(#2312 根因:#2308/#2311/#2312 连续改了 prompts.py 默认值但没写 alembic)。
"""
# #2312 E2E问题2: 占位符别名兼容——运营DB模板可能用{fusion_result}等历史命名,
# 代码传 voiceover_script=。自动补别名避免"未提供待审核文案"。
_alias_map = {
"voiceover_script": ("fusion_result", "script", "copy_text"),
"storyboard_input": ("input_text", "brief", "用户需求"),
}
for _src_key, _aliases in _alias_map.items():
if _src_key in kwargs and kwargs[_src_key]:
for _alias in _aliases:
kwargs.setdefault(_alias, kwargs[_src_key])
body = _safe_format(template.system_prompt, kwargs)
# 防御性注入:GLOBAL_CONSTRAINTS 核心规则——若 DB 模板完全没有这些关键词则追加。
# 判定指纹用多个关键词组合,避免运营改了措辞后漏判。
if template.prompt_type in ("storyboard",) and body:
try:
from packages.application.viral_video.prompts import GLOBAL_CONSTRAINTS
_need_global = True
_fp_compliance = ("不承诺", "效果", "绝对化")
_fp_medical = ("医疗", "诊疗", "根治", "疗效", "治愈")
_has_c = any(k in body for k in _fp_compliance)
_has_m = any(k in body for k in _fp_medical)
if _has_c and _has_m:
_need_global = False
if _need_global:
body = body.rstrip() + "\n\n" + GLOBAL_CONSTRAINTS
except Exception:
pass
# {industry_redlines} 占位符缺失时,把运行时传入的红线内容直接追加到末尾。
ir = kwargs.get("industry_redlines", "")
_ir_fps = (
"【养生/健康/理疗行业合规红线",
"【上次生成审核未通过的具体问题",
"【通用合规】",
"(非医疗健康行业,遵守通用广告法",
)
_already_has_ir = any(k in body for k in _ir_fps)
if ir and "{industry_redlines}" not in body and not _already_has_ir:
body = body.rstrip() + "\n\n" + ir
example = (template.example_output or "").strip()
if not example:
return body
@@ -260,6 +321,15 @@ def render_system_prompt(template: PromptTemplate, **kwargs) -> str:
def render_user_prompt(template: PromptTemplate, **kwargs) -> str:
r"""填充 user_prompt_template 占位符;example_output 存在时作为 few-shot 样例追加到 user 消息末尾,
配合 \_build_example_exchange 拼多轮 messages,LLM 收到完整「示例输入→示例输出」对齐格式。"""
# #2312 E2E问题2: 同 render_system_prompt,补占位符别名
_alias_map = {
"voiceover_script": ("fusion_result", "script", "copy_text"),
"storyboard_input": ("input_text", "brief", "用户需求"),
}
for _src_key, _aliases in _alias_map.items():
if _src_key in kwargs and kwargs[_src_key]:
for _alias in _aliases:
kwargs.setdefault(_alias, kwargs[_src_key])
body = _safe_format(template.user_prompt_template, kwargs)
example = (template.example_output or "").strip()
if not example:
+121 -24
View File
@@ -15,19 +15,67 @@ example_output / is_active。
from __future__ import annotations
# 所有文案类 Prompt 自动注入的硬约束
# 所有文案类 Prompt 自动注入的硬约束(#2312: 加强医疗/养生行业红线)
GLOBAL_CONSTRAINTS = """【必须遵守的硬约束】
1. 不编造时间:不写"今年最新""2024 爆款"等会过时的时间表述。
2. 不承诺效果:不写"保证""一定""100%有效""包治百病"等绝对化用语。
2. 不承诺效果:不写"保证""一定""100%有效""包治百病"等绝对化用语,不写任何效果承诺。
3. 不编造价格、销量、认证、奖项:除非用户在文案中明确给出,否则一律不写。
4. 符合广告法及平台社区规范。
5. 只描述图片中真实可见的内容,看不到的不瞎猜。"""
4. 符合广告法及平台社区规范,不触碰医疗/养生/金融等敏感行业红线。
5. 只描述图片中真实可见的内容,看不到的不瞎猜。
6. 不出现医疗/诊疗/治疗/治愈/疗效/根治/对症/药效/偏方/秘方/药到病除/一用就好/立刻见效/特效/克星/急救/救星/神药/祖传/宫廷秘方/一贴灵/一抹就好等宣称诊疗或疗效的词汇。
7. 养生/按摩/理疗/推拿/养生馆/调理类门店文案:只写"放松""舒缓""缓解疲劳""舒服""松快""解乏""轻松""舒展""按完轻松多了"等感受类表达,严禁暗示治病、治病根、诊疗、根治、对症、疗效、专家诊断、老师一搭手就知道问题在哪等越界表述。
8. 不冒充医生/专家/老师做诊疗判断,不写"老师帮你看看""一搭手就知道""哪儿疼治哪儿""对症调理"等暗示诊断/治疗的表述。"""
# 医疗/养生/保健/理疗行业强约束(当 industry 命中 HEALTH_INDUSTRY_KEYWORDS 时额外注入)
HEALTH_INDUSTRY_REDLINES = """【养生/健康/理疗行业合规红线(本行业必须严格遵守)】
1. 严禁暗示诊疗/治疗/治愈:禁止出现"治疗""治愈""治好""根治""对症""诊疗""看病""就诊""疗效""药效""见效""克星""救星""药到病除""一用就好""立刻见效""特效""一贴灵""一抹就好"等词。
2. 严禁诊断暗示:禁止出现"帮你看看""一搭手就知道""哪儿有问题""查出""诊断""判断"等暗示专业诊断的表述;工作人员不能被描述成具备诊断能力的"老师""大夫""医生""专家"。
3. 严禁功效承诺:禁止承诺"能治好""贴了就好""按完就不疼""根治""永不复发""药到病除""立刻缓解"等。
4. 身体部位疼痛描述只能作为**顾客主观感受的共情钩子**,不能接"我们能治/能好/能根除"的承诺。正确示范:「肩膀酸了吧?来这儿按一按,松快松快」;错误示范:「肩颈疼别忍着,让老师帮你看看,一搭手就知道问题在哪」。
5. 门店/服务只能描述成"放松""舒缓""缓解疲劳""舒服""松快""解乏""轻松""舒展""休息一下"这类纯感受/体验类词。
6. 不要出现"膏药""针灸""艾灸""中药""方子""疗程""对症""偏方""秘方""祖传""宫廷秘方"等医疗/药方相关词。
7. 不要引导"别贴膏药""别吃药""别去医院"等贬低正规医疗的表述。
8. 不要使用"颈肩腰腿,哪儿酸哪儿胀"这类像中医问诊的话术,改为"肩膀酸、腰背紧,想松快一下"等消费者自我感受的口语化表达。"""
# 判定健康/养生行业的关键词(命中其一即注入 HEALTH_INDUSTRY_REDLINES)
HEALTH_INDUSTRY_KEYWORDS: tuple[str, ...] = (
"养生",
"健康",
"理疗",
"推拿",
"按摩",
"艾灸",
"针灸",
"正骨",
"康复",
"中医",
"经络",
"穴位",
"肩颈",
"腰腿",
"筋骨",
"调理",
"保健",
"SPA",
"spa",
"养生馆",
"按摩店",
"御众堂",
"月子",
"产后修复",
"产康",
"足疗",
"足浴",
"盲人按摩",
)
# 负向提示(注入 storyboard / 视频生成负面词)
NEGATIVE_RULES = """【反套路化要求】
禁止使用"家人们谁懂啊""绝绝子""宝子们""家人们""太绝了""yyds"等烂大街网络词;
禁止使用"很近"等错别字,应使用"最近";
禁止固定模板化开头;语言要像真人朋友之间的分享,自然、具体、有信息量。"""
禁止"很近"等错别字,应使用"最近";
禁止固定模板化开头;语言要像真人朋友之间的分享,自然、具体、有信息量。
禁止医疗诊疗类词汇(治疗/治愈/根治/疗效/特效/药到病除/一用就好/对症/偏方/秘方/一搭手就知道/帮你看看等)。
禁止效果承诺(包治/根治/立刻见效/永不复发/一用就好等)。"""
# 输出禁用套路词(测试/reviewer/worker 三处共享)
# 注:广告法绝对化用语(如"最""第一""100%")在 worker 侧 _quick_compliance_blacklist_check 单独做本地替换,
@@ -126,17 +174,64 @@ _STORYBOARD_SYSTEM = (
+ """</negative>
</script>
## 写作要求
1. 口播台词:像真人面对镜头说话,短句、口语化、有停顿有情绪,开头 3 秒给出钩子;不要书面腔,不要机械报参数。
2. <shot> 只写6项摄影参数(景别/机位高度/焦段/光圈/运镜),简短不超过20字;<visual> 写观众会看到的画面主体/场景/光线/氛围;<action_details> 写人物动作/表情/物品操作细节(真人出镜必填)。三字段各司其职,不要混写。
3. copy_display_markdown:直接展示给最终用户的文案,用 Markdown 写成自然、流畅、有感染力的成片文案,可用小标题与短句组织;不要做字段列表,不要出现"镜头一/台词:"这类制作说明。
4. 内容必须来自图片观察与用户给出的信息,不编造卖点、不夸大、不使用绝对化用语和虚假承诺。
5. reference_image_index 填本镜参考图片序号(从 0 开始),没有合适参考图填 -1。
6. 分镜数量与时长匹配总时长,节奏紧凑。
7. 【字数/镜头数/时间轴硬约束】:严格遵守 user_prompt 里给出的 {duration_constraint_text},宁少勿多。
8. 每个 clip 必须分配一个 reference_image_index(从 0 开始的图片序号),没有合适图片填 -1。
9. 必须严格按<marketing_purpose><target_audience><persona><viral_structure><language><industry>指定的参数写文案和分镜,不能忽略任何一项用户参数。
10. 禁止使用"很近"等错别字,统一使用"最近"。"""
"""
+ GLOBAL_CONSTRAINTS
+ """
{industry_redlines}
## 【文案创作四铁律】(最优先级,必须严格遵守)
### 铁律一:开头3秒——必须是正在发生的事,禁止亮广告身份
- 第一句话/第一个画面必须是「正在发生的事」:正在进行的对话、冲突、悬念、反常识瞬间、当场抓包、具体场景中的人
- ❌ 绝对禁止以下开头(这些是广告身份证,观众0.5秒划走):
「大家好/我是XX/我干这行XX年了/你是否/很多人/人过XX/你有没有发现/今天给大家推荐/家人们」等自我介绍、痛点科普、泛泛而谈开场
- 前3秒不要亮店名/品牌名/「来找我」「来我店」这类推销词
- 开头台词要短、有冲击力、让人想继续看(2-8个字最佳),像"开个价吧""又疼?""你这肩膀硬得跟石板似的""昨天来个顾客进门就哭"
### 铁律二:内容——像真人讲故事,禁止抽象词堆砌
- 文案要像真人在对话或讲故事,不是在念广告;不要一个人干巴巴讲道理,尽量有"人物"和"对话"感(独白也要有场景代入,像在跟人掏心窝子说话)
- 必须有情绪起伏:不能从头到尾一个腔调,全片至少要有2-3个情绪转折点(惊讶/好笑/好奇/感动/反转)
- 禁止抽象形容词堆砌:❌「专业/靠谱/实惠/舒服/松快/效果好/品质好/值得信赖/服务周到/环境好」这些空词一律不准写
- 卖点必须场景化、数字具体化、有反差梗:
✅ 不说「肩膀放松」→说「按完你今晚能扛着孙子上三楼不喘气」
✅ 不说「效果好」→说「昨天张哥按完在我这睡了半小时,呼噜打隔壁来敲门」
✅ 不说「专业」→说「这手劲我练了二十三年,比你老公给你揉的准十倍」
✅ 不说「舒服」→说「按完那一下,你整个人跟面条似的软在那」
- 可以用反套路/反转/自嘲/幽默/当场抓包/顾客反应来增加记忆点;人物对话比单人独白吸引力高3倍
- 所有描述要能"看见画面"——读者脑子里能浮现出具体场景、人物表情、动作,而不是抽象评价
### 铁律三:结尾CTA——好奇心驱动,禁止指令式推销
- ❌ 禁止指令式硬推CTA:「快来吧/赶紧来/欢迎光临/不要错过/点击购买/赶紧试试/走过路过不要错过/机不可失/先到先得/错过后悔一辈子」
- ✅ 用好奇心/互动钩子驱动CTA:
- 提问互动式:「你摸摸你肩膀这根筋,是不是一按就酸?评论区告诉我」
- 悬念留钩式:「昨天那个张哥,按完当场睡了半小时——你猜他啥情况?」
- 轻量推荐式:「路过可以进来试试,不好算我的」
- 破梗自嘲式:「我知道你以为我要推销了——其实真不是,你试试就知道」
- CTA要自然,像朋友随口说一句,不要像销售在逼单
### 铁律四:语言风格——像朋友聊天,禁止广告腔/服务腔/说教腔
- 短句为主(每句5-15字最佳),像口语不像书面语;不要长句/排比句/对仗句/朗诵腔
- 禁止以下腔调:
- 服务腔:「竭诚为您服务/欢迎莅临/您的满意是我们的追求/宾至如归」
- 广告腔:「限时特惠/重磅来袭/好评如潮/销量领先/品质保证」
- 长辈说教腔:「听我一句劝/我跟你说/你不懂/年轻人啊/过来人告诉你」
- 主播带货腔:「家人们/宝子们/321上链接/买它/OMG」
- 要像:朋友聊天、当场发生的事、一个小故事、两个熟人在拌嘴、师傅边干活边随口搭话
- 【重要】以上铁律不能覆盖GLOBAL_CONSTRAINTS合规规则,医疗/养生类仍不能有诊疗/疗效承诺;但表达方式必须变——合规的前提下,把"松快""舒服"变成具体场景描述("按完在我这睡着了""出门时脚步轻了"),而不是删掉所有具体内容只留抽象词
## 写作要求(格式与技术规范)
1. 口播台词必须遵守上方【文案创作四铁律】,像真人对话、短句口语、有情绪起伏、有场景、有反转、有钩子
2. <shot> 只写6项摄影参数(景别/机位高度/焦段/光圈/运镜),简短不超过20字;<visual> 写观众会看到的画面主体/场景/光线/氛围;<action_details> 写人物动作/表情/物品操作细节(真人出镜必填)。三字段各司其职,不要混写
3. copy_display_markdown:直接展示给最终用户的文案,用 Markdown 写成自然、流畅、有故事感的成片文案,可用小标题与短句组织;不要做字段列表,不要出现"镜头一/台词:"这类制作说明
4. 内容必须来自图片观察与用户给出的信息,不编造卖点/价格/销量/认证/奖项、不夸大、不使用绝对化用语和虚假承诺;卖点要场景化表达(铁律二)
5. reference_image_index 填本镜参考图片序号(从 0 开始),没有合适参考图填 -1
6. 分镜数量与时长匹配总时长,节奏紧凑(平均每镜2-3秒,开头1-2镜要更快)
7. 【字数/镜头数/时间轴硬约束】:严格遵守 user_prompt 里给出的 {duration_constraint_text},宁少勿多
8. 每个 clip 必须分配一个 reference_image_index(从 0 开始的图片序号),没有合适图片填 -1
9. 必须严格按<marketing_purpose><target_audience><persona><viral_structure><language><industry>指定的参数写文案和分镜,不能忽略任何一项用户参数
10. 禁止使用"很近"等错别字,统一使用"最近"
11. 前3秒第一镜画面必须是具体场景/人物动作/对话瞬间,禁止空镜/产品特写/品牌logo开场;第一镜必须有人有动作有情绪"""
)
_STORYBOARD_USER = """<marketing_purpose>{marketing_purpose}</marketing_purpose>
@@ -198,9 +293,11 @@ _STORYBOARD_EXAMPLE = """<script>
# ── 模板3:文案审核(合规/质量门禁)───────────────────────────────────
_REVIEW_SYSTEM = """你是一名短视频广告合规审核与文案优化专家。请审核下面这段口播文案:
1) 广告法与平台合规(绝对化用语、虚假承诺、医疗功效宣称、导流违规、套路烂梗词);
2) 口播是否自然、口语化、无书面腔;
3) 是否有明显错别字(例如把"最近"写成"很近")。
1) 广告法与平台合规(绝对化用语、虚假承诺、导流违规、套路烂梗词);
2) **医疗/养生/健康红线(重点审查)**:是否出现诊疗暗示("帮你看看""一搭手就知道""老师诊断""检查"等)、疗效/治愈承诺("治好""根治""见效""一用就好""药到病除""特效""克星""永不复发"等)、医疗术语("疗程""对症""膏药""针灸""中药""偏方""秘方""诊疗""治疗""就诊"等)、冒充医生/专家/老师做诊断、贬低正规医疗("别贴膏药""别吃药""别去医院"等);
3) 养生/按摩/理疗/推拿/保健类文案是否用了纯感受类表达(放松/舒缓/舒服/松快/解乏/轻松),而不是"治病/根治/疗效"类表达;
4) 口播是否自然、口语化、无书面腔;
5) 是否有明显错别字(例如把"最近"写成"很近")。
只输出 XML,结构:
<review>
@@ -237,18 +334,18 @@ DEFAULT_TEMPLATES: list[dict] = [
"is_active": True,
},
{
"name": "编导级分镜 v3.1",
"name": "编导级分镜 v3.2",
"prompt_type": "storyboard",
"version": 4,
"version": 5,
"system_prompt": _STORYBOARD_SYSTEM,
"user_prompt_template": _STORYBOARD_USER,
"example_output": _STORYBOARD_EXAMPLE,
"is_active": True,
},
{
"name": "文案审核 v2",
"name": "文案审核 v3",
"prompt_type": "review",
"version": 2,
"version": 3,
"system_prompt": _REVIEW_SYSTEM,
"user_prompt_template": _REVIEW_USER,
"example_output": _REVIEW_EXAMPLE,
@@ -39,6 +39,44 @@ _EXAGGERATION_PATTERNS = [
r"一喷(就|全|100)",
]
# 本地规则:医疗/养生/诊疗红线(#2312:出片前最后一道本地兜底,命中即 error)
# 注意:这些词/句式出现在养生/理疗/按摩/保健/康复类文案中几乎必然违规,直接挡
# 本地规则做快速兜底,LLM 审核是主防线(review prompt v3 已加强医疗维度,语义判断更准)
_MEDICAL_REDLINE_PATTERNS = [
# 疗效/治愈/根治/效果承诺
(r"包治(百病|各种|颈肩|腰腿|风湿|颈椎|腰椎)?", "出现诊疗承诺:'{hit}',暗示包治违反广告法与医疗合规"),
(r"根[治除](?!本)", "出现根治/根除表述:'{hit}',非医疗机构不得承诺根治"),
(r"(永不复发|药到病除)", "出现疗效承诺:'{hit}'"),
(
r"一(?:用|贴|抹|喷|吃|服|针|喝)[^,。!?]{0,3}(?:就|即|立)(?:好|见效|灵|愈|止痛)",
"出现'一X就好'类即时疗效承诺:'{hit}'",
),
(r"(?:立刻|马上|立即|瞬间|当天|一次就)(?:见效|止痛|不痛|康复|止?痛|治好)", "出现即时效果承诺:'{hit}'"),
(r"特[效药贴针酒]|神药|神贴|神针|妙药", "出现神/特效类违规表述:'{hit}'"),
# 诊断暗示(工作人员"搭手就知道""帮你看看哪有问题")
(r"一搭手就知道", "出现诊断暗示:'{hit}',非医疗机构按摩师/老师不能做诊断"),
(
r"(?:老师|师傅|大夫|医生|专家|医师)(?:帮你|给你|为你|一)(?:看看|检查|诊断|判断|瞧瞧|搭手)",
"出现诊断暗示:'{hit}',工作人员不能被描述为做诊断",
),
(r"(?:帮你|给你|为你)(?:看看(?:问题|毛病|病|哪儿|哪)?|检查(?:一下)?|诊断)", "出现诊断暗示:'{hit}'"),
# 贬低正规医疗/引导弃医
(
r"别(?:急着|忙着|光|总|一直)?(?:贴膏药|吃药|上医院|去医院|看医生|打针|拖|扛|忍(?:着|着不)?|硬扛)|不要(?:急着|忙着)?(?:贴膏药|吃药|上医院|去医院|看医生|打针)",
"出现贬低/规避正规医疗的引导:'{hit}'",
),
# 医疗术语(按摩/养生门店正常营销不应出现)
(
r"(?:疗[程效]|对症(?:下药)?|诊疗|就诊|就医|医嘱|病(?:灶|情|症)|处[方箋])",
"出现医疗术语:'{hit}',非医疗机构文案应使用感受类表达",
),
(
r"哪儿酸哪儿胀|哪(?:儿|里)(?:疼|酸|胀|痛|不舒服|不适)[^,。!?]{0,8}(?:就知道|一看就知|老师|师傅|大夫|把下脉)",
"出现中医问诊式诊断话术:'{hit}',应改为顾客自我感受表达",
),
(r"(?:偏方|秘方|宫廷秘方|祖传秘方)", "出现偏方/秘方类违规表述:'{hit}'"),
]
# 本地规则:套路烂梗/明显错别字(与 prompts.COMPLIANCE_BLACKLIST 同步)
_VIOLATION_PATTERNS = [re.escape(p) for p in COMPLIANCE_BLACKLIST] + [
r"最(好|强|牛|便宜|美|棒)", # 广告法极限词(最X)
@@ -173,6 +211,19 @@ class Reviewer:
text="出现违规/套路词或错别字:" + self._hit(text, pattern),
)
)
# #2312: 医疗/养生/诊疗红线扫描(命中即 error)
for pattern, msg_tpl in _MEDICAL_REDLINE_PATTERNS:
m = re.search(pattern, text)
if m:
hit = m.group(0)
issues.append(
ReviewIssue(
dimension="医疗合规",
severity="error",
location="voiceover_script",
text=msg_tpl.format(hit=hit),
)
)
return issues
@staticmethod
+32 -3
View File
@@ -159,10 +159,39 @@ VIRAL_VIDEO_MODEL_CONFIG: dict[str, dict] = {
def get_viral_video_model_config(model_key: str | None) -> dict:
"""获取模型配置,未知 key 回落到默认 seedance-2.5。"""
key = (model_key or "").strip().lower()
if key and key in VIRAL_VIDEO_MODEL_CONFIG:
"""获取模型配置,未知 key 回落到默认 seedance-2.5。
#2312 E2E问题4: 支持多种别名/变体查找,防止前端或内部传model_id/大小写/横杠变体
# (如 wan3.0-video / Wan-3.0 / wan_3_0 等)误回落 seedance-2.5。
"""
raw = (model_key or "").strip()
if not raw:
return VIRAL_VIDEO_MODEL_CONFIG["seedance-2.5"]
key = raw.lower()
if key in VIRAL_VIDEO_MODEL_CONFIG:
return VIRAL_VIDEO_MODEL_CONFIG[key]
# 别名归一化:横杠/下划线/点/空格统一去掉,做模糊匹配
_norm = key.replace("-", "").replace("_", "").replace(".", "").replace(" ", "")
# 同时支持 model_id 反向查找(防止传 wan3.0-video 这类 model_id 串)
for _k, _cfg in VIRAL_VIDEO_MODEL_CONFIG.items():
_k_norm = _k.replace("-", "").replace("_", "").replace(".", "").replace(" ", "")
if _k_norm == _norm:
return _cfg
_mid = str(_cfg.get("model_id", "")).lower().replace("-", "").replace("_", "").replace(".", "")
if _mid and _mid == _norm:
return _cfg
# wan 系列兜底(任何包含 wan 的未知key归到 wan-3.0,而不是 seedance)
if "wan" in key:
logger = __import__("logging").getLogger(__name__)
logger.warning("[points_rules] 未知wan模型key=%r,归一化为wan-3.0", model_key)
return VIRAL_VIDEO_MODEL_CONFIG["wan-3.0"]
# seedance 系列同理
if "seedance" in key and "2.0" in key and "fast" in key:
return VIRAL_VIDEO_MODEL_CONFIG["seedance-2.0-fast"]
if "seedance" in key and "mini" in key:
return VIRAL_VIDEO_MODEL_CONFIG["seedance-2.0-mini"]
if "seedance" in key and "2.0" in key:
return VIRAL_VIDEO_MODEL_CONFIG["seedance-2.0"]
return VIRAL_VIDEO_MODEL_CONFIG["seedance-2.5"]
+2
View File
@@ -26,6 +26,7 @@ class StoragePort(ABC):
file_or_path: str | Path | object,
storage_key: str,
content_type: str = "application/octet-stream",
extra_headers: dict | None = None,
) -> str:
"""上传文件到存储,返回公开 URL。
@@ -33,6 +34,7 @@ class StoragePort(ABC):
file_or_path: 本地文件路径(str/Path)或类文件对象
storage_key: 目标存储键
content_type: MIME 类型
extra_headers: 额外请求头(如 x-oss-object-acl)
Returns:
公开访问 URL
+1 -1
View File
@@ -180,7 +180,7 @@ class DashScopeClient:
"audio": bool(generate_audio),
}
if ratio and ratio != "adaptive":
params["aspect_ratio"] = ratio
params["ratio"] = ratio
payload: dict[str, Any] = {
"model": model,
+12 -3
View File
@@ -183,22 +183,26 @@ class SharedStorageService(StoragePort):
file_or_path: str | Path | object,
storage_key: str,
content_type: str = "application/octet-stream",
extra_headers: dict | None = None,
) -> str:
if self.bucket is None:
raise RuntimeError("OSS storage is not configured")
try:
headers: dict = {"Content-Type": content_type}
if extra_headers:
headers.update(extra_headers)
if isinstance(file_or_path, (str, Path)):
self.bucket.put_object_from_file(
storage_key,
str(file_or_path),
headers={"Content-Type": content_type},
headers=headers,
)
else:
file_or_path.seek(0)
self.bucket.put_object(
storage_key,
file_or_path,
headers={"Content-Type": content_type},
headers=headers,
)
return f"{self.public_url}/{storage_key}"
except Exception as e:
@@ -208,6 +212,7 @@ class SharedStorageService(StoragePort):
self,
local_path: str | Path,
storage_key: str,
extra_headers: dict | None = None,
) -> Optional[str]:
local_path = Path(local_path)
if not local_path.exists():
@@ -230,6 +235,9 @@ class SharedStorageService(StoragePort):
use_multipart = False
file_size = 0
headers: dict = {}
if extra_headers:
headers.update(extra_headers)
if use_multipart:
logger.info(
"大文件分片上传(internal): key=%s size=%.1fMB part=%dMB threads=%d",
@@ -245,9 +253,10 @@ class SharedStorageService(StoragePort):
multipart_threshold=OSS_MULTIPART_THRESHOLD,
part_size=OSS_PART_SIZE,
num_threads=OSS_MULTIPART_NUM_THREADS,
headers=headers or None,
)
else:
self.bucket.put_object_from_file(storage_key, str(local_path))
self.bucket.put_object_from_file(storage_key, str(local_path), headers=headers or None)
result["url"] = f"{self.public_url}/{storage_key}"
except Exception as e:
result["error"] = e
+81
View File
@@ -486,6 +486,87 @@ class TestLipsyncServiceUnit:
assert call_kwargs.kwargs["audio_url"] == "https://example.com/direct-audio.mp3"
assert job.audio_url == "https://example.com/direct-audio.mp3"
def test_create_job_presynth_backfills_script_text(self, mock_mediakit, mock_cosyvoice):
"""预合成模式 script_text 为空时,从 sentence_timings 拼接兜底.
背景:前端 #1875 起预合成 payload 不带 script_text,导致 job.script_text
落库为空,Ditto 任务 script_len=0、情绪分析被跳过。
"""
from app.services.lipsync_service import LipsyncService
mock_db = MagicMock()
svc = LipsyncService(
mock_db,
client=mock_mediakit,
cosyvoice_service=mock_cosyvoice,
voice_clone_repo=MagicMock(),
)
svc.settings.use_gpu_lipsync = False
timings = [
{"index": 0, "text": "大家好,", "start_time": 0.0, "end_time": 1.0},
{"index": 1, "text": "欢迎来到直播间。", "start_time": 1.0, "end_time": 2.5},
]
job = svc.create_job(
user_id="user-1",
video_url="https://example.com/video.mp4",
audio_url="https://example.com/audio.mp3",
audio_duration=2.5,
sentence_timings=timings,
script_text="", # 前端预合成 payload 不带文案
)
assert job.script_text == "大家好,欢迎来到直播间。"
def test_create_job_presynth_keeps_supplied_script_text(self, mock_mediakit, mock_cosyvoice):
"""预合成模式显式传了 script_text 时,保留原文不做拼接."""
from app.services.lipsync_service import LipsyncService
mock_db = MagicMock()
svc = LipsyncService(
mock_db,
client=mock_mediakit,
cosyvoice_service=mock_cosyvoice,
voice_clone_repo=MagicMock(),
)
svc.settings.use_gpu_lipsync = False
timings = [
{"index": 0, "text": "分句一", "start_time": 0.0, "end_time": 1.0},
]
job = svc.create_job(
user_id="user-1",
video_url="https://example.com/video.mp4",
audio_url="https://example.com/audio.mp3",
audio_duration=1.0,
sentence_timings=timings,
script_text="原始文案,含标点。",
)
assert job.script_text == "原始文案,含标点。"
def test_create_job_presynth_empty_timings_falls_back_to_direct(self, mock_mediakit, mock_cosyvoice):
"""sentence_timings 空列表时 is_pre_synth=False,退化为直接音频模式(语义固化)."""
from app.services.lipsync_service import LipsyncService
mock_db = MagicMock()
svc = LipsyncService(
mock_db,
client=mock_mediakit,
cosyvoice_service=mock_cosyvoice,
voice_clone_repo=MagicMock(),
)
svc.settings.use_gpu_lipsync = False
job = svc.create_job(
user_id="user-1",
video_url="https://example.com/video.mp4",
audio_url="https://example.com/audio.mp3",
sentence_timings=[],
script_text="",
)
# 直接音频模式:无 timings 可拼,script_text 保持空(不报错)
assert job.script_text == ""
mock_mediakit.submit_lipsync.assert_called_once()
class TestErrorHandling:
"""v3: 音色解析与错误码在 service 层处理,路由层做 HTTP 状态码映射."""