Compare commits

...

192 Commits

Author SHA1 Message Date
CI Bot bee59b7f27 ci: retrigger staging build for ditto emotion timeline deployment
CI/CD Pipeline / Build Production API Image (push) Blocked by required conditions
CI/CD Pipeline / Build Production Web Image (push) Blocked by required conditions
CI/CD Pipeline / Build Production Worker Image (push) Blocked by required conditions
CI/CD Pipeline / Deploy Production (push) Blocked by required conditions
CI/CD Pipeline / Production Browser E2E (push) Blocked by required conditions
CI/CD Pipeline / Canary Release to Production (push) Blocked by required conditions
CI/CD Pipeline / CI Gate (push) Blocked by required conditions
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
AI Code Review / AI Code Review (pull_request) Has started running
CI/CD Pipeline / Validate - Style (push) Has started running
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Validate - Security (push) Has started running
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has started running
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Unit Tests (push) Has started running
CI/CD Pipeline / Integration Tests (push) Has started running
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 Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) 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 / 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 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 Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 30s
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 1m11s
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 / Build Staging API Image (push) Successful in 1m6s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m45s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m52s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m19s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m24s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m9s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m35s
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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m46s
CI/CD Pipeline / Staging E2E Tests (push) Has started running
CI/CD Pipeline / Staging API Integration Tests (push) Has started running
CI/CD Pipeline / ACR Image Cleanup (push) Has started running
Previous push CI runs were cancelled by concurrency group.
This triggers a fresh build with the merged changes:
- PR #2244: OSS sign_url slash_safe=True fix
- PR #2245: Ditto LLM emotion timeline feature
2026-10-08 17:21:59 +08:00
CI Bot 4bd4a6c390 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 6s
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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 8s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
CI/CD Pipeline / Frontend Lint (push) 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 / 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 / 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 / Check push changed paths (push) Successful in 32s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 1m1s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 43s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m25s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m20s
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 3m20s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m42s
CI/CD Pipeline / Integration Tests (push) Successful in 6m42s
CI/CD Pipeline / Validate - Style (push) Successful in 7m7s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m59s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 7m55s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m37s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m45s
AI Code Review / AI Code Review (pull_request) Successful in 10m9s
CI/CD Pipeline / Unit Tests (push) Failing after 13m44s
CI/CD Pipeline / Validate - Security (push) Successful in 15m42s
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-08 08:30:49 +00:00
xiaoxia aa898ff0c8 Merge pull request 'feat: Ditto LLM情绪驱动表情时间线(Ditto Emotion Timeline)' (#2245) from feat/ditto-emotion-timeline into develop
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 3s
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 9s
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 / Check push changed paths (push) Successful in 31s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m21s
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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m37s
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 / Integration Tests (push) Successful in 6m32s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m43s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m32s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m21s
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 API Image (pull_request) Has been skipped
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 / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (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 / Validate - Python (mypy + alembic) (push) Successful in 8m4s
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 / Build Staging Worker Image (push) Successful in 1m16s
AI Code Review / AI Code Review (pull_request) Successful in 6m36s
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 / Build Staging Web Image (push) Has been cancelled
2026-10-08 16:21:23 +08:00
xiaoxia fb0d429bd7 feat(ditto): LLM情绪驱动表情(emo_timeline)#2076后续
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 / 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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 53s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 33s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m30s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m15s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m20s
AI Code Review / AI Code Review (pull_request) Successful in 6m58s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 7m6s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 8m31s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m10s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 14m5s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 17m17s
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 / CI Gate (pull_request) Failing after 2s
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
- 新增 packages/application/ditto_emotion_service.py:
  - 分句(按。!?;正则切分)
  - LLM调用(复用DoubaoClient,模型/temp/timeout/max_tokens全部走配置)
  - JSON解析+校验(禁用emo 0/1/2/7→中性,intensity clamp 0.05-1.0)
  - LRU缓存(相同文案不重复分析)
  - 时间对齐(有sentence_timings精确对齐,无则按字数比例分配)
  - 容错:任何异常返回空字符串,降级GPU端关键词匹配/中性表情
- DittoClient.generate/generate_and_persist 新增 emo_timeline/blend_frames 参数:
  - blend_frames默认12(从配置读取)
  - emo_timeline有值时才加入payload
- lipsync_ditto.py Celery任务接入:音频下载→时长探测→情绪分析→emo_timeline传入Ditto
- config/base.py 新增7个情绪配置项 + blend_frames默认值改为12
- 新增packages/application/prompts/ditto_emotion.txt提示词模板(27行)
- 26个单元测试全通过(含分句/解析/对齐/缓存/容错)
2026-10-08 16:19:19 +08:00
xiaoxia 606f6988b5 Merge pull request 'fix: OSS sign_url 添加 slash_safe=True 防止签名URL 403' (#2244) from fix/oss-sign-url-slash-safe into develop
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 (push) Successful in 32s
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 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m26s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m10s
CI/CD Pipeline / Build Staging API Image (push) Successful in 26s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m52s
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 Worker Image (push) Successful in 2m11s
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
PR Automation / Auto Merge on CI Green + Approved (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 / Build Production Web 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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging 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 / 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 / Validate - Python (mypy + alembic) (push) Successful in 7m58s
CI/CD Pipeline / Integration Tests (push) Successful in 7m27s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m12s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m30s
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 8m59s
AI Code Review / AI Code Review (pull_request) Successful in 6m33s
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 / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m37s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m5s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m41s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m56s
CI/CD Pipeline / Unit Tests (push) Failing after 16m18s
CI/CD Pipeline / Validate - Security (push) Successful in 18m14s
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 / Build Production Web 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-08 14:59:12 +08:00
CI Bot 733d8bb75c fix: OSS sign_url 添加 slash_safe=True 防止路径斜杠被编码为 %2F
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 / 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 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m4s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m38s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m39s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 16s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
AI Code Review / AI Code Review (pull_request) Successful in 7m8s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 7m34s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 8m19s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 8m50s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m27s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 17m23s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 18m47s
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 / CI Gate (pull_request) Failing after 1s
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
sign_url() 默认将路径中的 / 编码为 %2F,导致 OSS 服务端签名校验
不匹配(SignatureDoesNotMatch 403),所有预签名 URL 无法访问。

影响范围:Ditto 口型视频 output_video_url、uploads 目录所有签名 URL。
修复:传递 slash_safe=True 保持路径中的 / 不被编码。
2026-10-08 14:58:51 +08:00
CI Bot e83048b7ec 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 29s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 27s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m1s
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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m7s
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 / 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 / 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 40s
CI/CD Pipeline / Build Staging API Image (push) Successful in 41s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m47s
PR Automation / Auto Merge on CI Green + Approved (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 / Deploy Staging (Watchtower auto-deploy) (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 / 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
AI Code Review / AI Code Review (pull_request) Successful in 6m56s
CI/CD Pipeline / Integration Tests (push) Successful in 6m34s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m26s
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 7m27s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m8s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 7m34s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m7s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m45s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m58s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m10s
CI/CD Pipeline / Unit Tests (push) Failing after 14m52s
CI/CD Pipeline / Validate - Security (push) Successful in 17m1s
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
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
2026-10-08 06:27:51 +00:00
CI Bot a3a8d2561d ci: trigger staging rebuild for ditto timeout fix v4
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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
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 3s
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 / 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 / Frontend Lint (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 / Check push changed paths (push) Successful in 30s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
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 52s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m28s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m16s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m1s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m10s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m54s
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 / Integration Tests (push) Successful in 6m6s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m6s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 7m13s
AI Code Review / AI Code Review (pull_request) Successful in 7m8s
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
2026-10-08 14:18:54 +08:00
xiaoxia-bot 7b6dfdc29f ci: trigger staging rebuild for ditto timeout fix
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 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) 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 30s
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 / 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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m55s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m52s
CI/CD Pipeline / Build Staging API Image (push) Successful in 40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m5s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 41s
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
PR Automation / Auto Merge on CI Green + Approved (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 API Image (pull_request) Successful in 2m29s
CI/CD Pipeline / CI Gate (pull_request) Successful in 8s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m16s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m12s
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 / 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
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
2026-10-08 14:03:25 +08:00
xiaoxia b5e225e62a ci: trigger staging rebuild for ditto timeout fix
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 / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (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 / Unit Tests (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 / 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 / Check push changed paths (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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 / 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 / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 35s
2026-10-08 14:02:57 +08:00
xiaoxia 2141ddb19b fix: Ditto 连接超时缩短至10s + 网络错误不重试,快速回退MediaKit (#2076) (#2243)
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 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 19s
CI/CD Pipeline / Check push changed paths (push) Successful in 52s
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 (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 Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (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 / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 / 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 / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (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 cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-08 14:00:18 +08:00
xiaoxia 3503542ec2 fix: Ditto 连接超时缩短至10s + 网络错误不重试,快速回退MediaKit (#2076) (#2243)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (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) Blocked by required conditions
CI/CD Pipeline / Unit Tests (push) Blocked by required conditions
CI/CD Pipeline / Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Frontend Lint (push) Blocked by required conditions
CI/CD Pipeline / Frontend Unit Tests (push) Blocked by required conditions
CI/CD Pipeline / PR Build API Image (push) Blocked by required conditions
CI/CD Pipeline / PR Build Web Image (push) Blocked by required conditions
CI/CD Pipeline / PR Build Worker Image (push) Blocked by required conditions
CI/CD Pipeline / Check push changed paths (push) Waiting to run
CI/CD Pipeline / Build Staging API Image (push) Blocked by required conditions
CI/CD Pipeline / Build Staging Web Image (push) Blocked by required conditions
CI/CD Pipeline / Build Staging Worker Image (push) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging API Image (push) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging Web Image (push) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Blocked by required conditions
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Blocked by required conditions
CI/CD Pipeline / Staging E2E Tests (push) Blocked by required conditions
CI/CD Pipeline / Staging API Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Build Production API Image (push) Blocked by required conditions
CI/CD Pipeline / Build Production Web Image (push) Blocked by required conditions
CI/CD Pipeline / Build Production Worker Image (push) Blocked by required conditions
CI/CD Pipeline / Deploy Production (push) Blocked by required conditions
CI/CD Pipeline / Production Browser E2E (push) Blocked by required conditions
CI/CD Pipeline / ACR Image Cleanup (push) Blocked by required conditions
CI/CD Pipeline / Canary Release to Production (push) Blocked by required conditions
CI/CD Pipeline / CI Gate (push) Blocked by required conditions
2026-10-08 13:59:51 +08:00
xiaoxia-bot 1a6f04b258 fix: staging 模板持久化 Ditto 环境变量,防止 CI 重建 .env 后丢失
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
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 / Check push changed paths (push) Successful in 10s
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 (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 - 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 / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (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 / 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 / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (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 / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 Production (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (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 / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (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
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-08 13:57:29 +08:00
xiaoxia-bot fe36a05c51 ci: trigger staging rebuild for ditto hotfix
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 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 / 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 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
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 / PR Build API 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 / 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 / Retag skipped Staging 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 30s
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 45s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m16s
CI/CD Pipeline / Build Staging API Image (push) Successful in 44s
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 API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m58s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 56s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m15s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m10s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m38s
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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 5m9s
CI/CD Pipeline / Validate - Style (push) Successful in 5m44s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m2s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m40s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 2m47s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m16s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m28s
CI/CD Pipeline / Unit Tests (push) Failing after 12m26s
CI/CD Pipeline / Validate - Security (push) Successful in 14m16s
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-08 12:14:03 +08:00
xiaoxia 12a8701283 fix: Ditto output_video_url 改用签名URL + 轮询跳过 ditto 前缀 (#2241)
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 (push) Successful in 39s
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 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m29s
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Staging API 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 / Unit Tests (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 / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
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 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 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 / Deploy Staging (Watchtower auto-deploy) (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 / PR Build API Image (pull_request) Successful in 44s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m34s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m13s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
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 / CI Gate (pull_request) Successful in 2s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-08 12:06:43 +08:00
xiaoxia 176a5cbfe3 Merge pull request 'fix(viral-video): WS初始快照补齐 image_analysis/copy_result,修复刷新后丢失分析结果和文案' (#2239) from fix/ws-initial-snapshot-missing-fields into develop
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 (push) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / 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 / 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 push changed paths (push) Successful in 20s
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 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 1m1s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m4s
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 / 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 1m34s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 35s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m21s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m49s
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 3m5s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m20s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / Integration Tests (push) Successful in 7m21s
CI/CD Pipeline / Validate - Style (push) Successful in 8m19s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 9m47s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 7m52s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m24s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 2m33s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m19s
CI/CD Pipeline / Validate - Security (push) Successful in 20m26s
CI/CD Pipeline / Unit Tests (push) Failing after 29m52s
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 / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / CI Gate (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
CI/CD Pipeline / Deploy Production (push) Has been skipped
2026-10-08 11:11:22 +08:00
xiaoxia c5e69db50d feat: Ditto 蚂蚁数字人口型服务对接(#2076) (#2240)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m20s
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 / Validate - Python (mypy + alembic) (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m54s
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 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 / PR Build Worker Image (pull_request) Successful in 1m26s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m35s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m37s
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 / Validate - Python (mypy + alembic) (push) Successful in 4m16s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m2s
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 / Validate - Style (push) Successful in 5m37s
AI Code Review / AI Code Review (pull_request) Successful in 6m30s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m45s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m4s
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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m52s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m24s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m59s
CI/CD Pipeline / Validate - Security (push) Successful in 10m51s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m30s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m53s
CI/CD Pipeline / Unit Tests (push) Failing after 13m25s
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 / Build Production API 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-08 10:47:02 +08:00
CI Bot 44bbe0f0e5 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 3s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 53s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 3m18s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m24s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m41s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m22s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m37s
AI Code Review / AI Code Review (pull_request) Successful in 6m45s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m32s
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 / CI Gate (pull_request) Failing after 8s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m39s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 23s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m24s
2026-10-08 02:45:13 +00:00
Xiaoxia Agent 92680c47f9 fix(viral-video): WS初始快照补齐 image_analysis/copy_result 字段,修复刷新后丢失分析结果和文案
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 / Build Staging API Image (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 / 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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m46s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m57s
AI Code Review / AI Code Review (pull_request) Has been cancelled
P0: 前端刷新或WS重连时,initial消息只有status,导致imageAnalysis state为null、识别描述区域不渲染。
修复:initial.data里按状态对齐worker事件结构,带上image_analysis/copy_result/storyboard/generated_copy_text;
copy_result复用已有_build_copy_result(job)(兼容v1.5老数据);中间态无业务字段时不塞空dict/list。
新增3个单测覆盖 image_analyzed / copy_generated / 中间态纯净快照。
2026-10-08 10:39:57 +08:00
xiaoxia b335fbbcce fix(viral-video): xml_parser 剥离 CDATA 包裹,修复 copy_display_markdown 前端泄露 (#2238)
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 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 / 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 / Validate - Style (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 (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 / Check push changed paths (push) Successful in 30s
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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m17s
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 / Build Staging API Image (push) Successful in 1m23s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m47s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m49s
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 4m41s
CI/CD Pipeline / Integration Tests (push) Successful in 4m58s
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m20s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m34s
CI/CD Pipeline / Validate - Style (push) Successful in 5m38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m12s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m51s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m54s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m36s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m24s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m39s
CI/CD Pipeline / Validate - Security (push) Successful in 9m49s
CI/CD Pipeline / Unit Tests (push) Failing after 12m8s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-08 02:36:03 +08:00
xiaoxia cc542f27d9 Merge pull request 'refactor(vision): v8 叙述优先架构大简化' (#2237) from refactor/vision-v8-narration-first into develop
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 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 / 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 / Check push changed paths (push) Successful in 31s
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 / PR Build API Image (pull_request) Successful in 1m5s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m23s
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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 43s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m26s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m7s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m5s
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 4m30s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m8s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m25s
AI Code Review / AI Code Review (pull_request) Successful in 7m27s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m42s
CI/CD Pipeline / Validate - Security (push) Successful in 8m15s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m1s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m40s
CI/CD Pipeline / Unit Tests (push) Failing after 14m53s
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-08 01:29:39 +08:00
CI Bot d42ab5ffa8 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 (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m33s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 4m11s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m15s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m27s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m36s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 4m47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m46s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m2s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m4s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 5m6s
AI Code Review / AI Code Review (pull_request) Successful in 7m3s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 7m47s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m34s
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 / CI Gate (pull_request) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m16s
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
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 35s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 3m59s
2026-10-07 17:14:09 +00:00
Xiaoxia Agent 74896727bb test(viral-video): 适配 v8/v3 叙述优先重构(products→images、删 intent/copy_fusion 用例)
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 if frontend-only change (pull_request) Successful in 1s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 3m37s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 4m5s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m10s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m3s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 5m28s
AI Code Review / AI Code Review (pull_request) Successful in 6m40s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 6m45s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 6m43s
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 / 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 Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Failing after 9m41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-08 01:04:27 +08:00
xiaoxia-test 1f6d10f861 refactor(vision): v8 叙述优先架构大简化,LLM直接产出最终文案
CI/CD Pipeline / Check push changed paths (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 / 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 / PR Build API Image (pull_request) Successful in 1m9s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m5s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m27s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m37s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m10s
AI Code Review / AI Code Review (pull_request) Successful in 7m5s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 13m19s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m45s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 13m54s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 20m42s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 23m55s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 34m36s
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) Failing after 1s
- image_analysis v8 prompt 重写:summary_markdown 自然叙述为主交付,结构化字段仅 type/name/brand/has_person,顶层 products 改 images
- assembler 1017→106:删除 brand 多级兜底与 colors/material/key_features 等全部细分字段处理,summary_markdown 兜底仅一句
- _prompt/fast_path/vlm_* 同步瘦身,删除 prompt 拼接旧 schema 与逐字段处理
- viral_video 删除 _step_intent_parsing(与脚本生成合并为一次 LLM 调用),intent_result 字段保留兼容老数据
- 脚本后处理仅 JSON 解析+基本字段补全,不改 LLM 文案;shots 保留供前端编辑
- storyboard v3 prompt 风格重写:口播口语化、画面有画面感、copy_display_markdown 流畅叙述
- 前端删除 vv-recog-line 全部硬编码字段,统一 markdown 渲染,编辑区不动
- 老数据 products→images 仅在读入时一次性转换,不保留双套逻辑
- Migration 105:重写版 v8 active / v7 deactivate,storyboard v3 更新
- 更新 vision 单测适配新格式

净减少约 1600 行
2026-10-07 22:21:17 +08:00
xiaoxia 3ee5a4042d Merge pull request 'feat: 提示词控制展示格式 - summary_markdown + copy_display_markdown' (#2236) from feature/prompt-controlled-display-format into develop
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 / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build API 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 3s
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 / 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 - 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 / 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 / Check push changed paths (push) Successful in 30s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m8s
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 1m4s
CI/CD Pipeline / Build Staging API Image (push) Successful in 47s
PR Automation / Auto Merge on CI Green + Approved (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 2m21s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 56s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m18s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m11s
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 / Frontend Unit Tests (push) Successful in 4m0s
AI Code Review / AI Code Review (pull_request) Successful in 7m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 4m25s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m41s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m56s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m38s
CI/CD Pipeline / Integration Tests (push) Successful in 13m54s
CI/CD Pipeline / Validate - Style (push) Successful in 14m31s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 17m46s
CI/CD Pipeline / Unit Tests (push) Failing after 20m24s
CI/CD Pipeline / Validate - Security (push) Successful in 35m30s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-07 19:46:29 +08:00
Xiaoxia Agent a979af1488 feat(web): ViralVideoPage markdown 渲染 summary_markdown + copy_display_markdown
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 / 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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m52s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m56s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m56s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m22s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m15s
AI Code Review / AI Code Review (pull_request) Successful in 7m2s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m1s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 10m38s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m51s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m42s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 16m58s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m2s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 2m22s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 32m52s
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) Failing after 4s
- 引入 marked 轻量 markdown 库(gfm)
- 识别描述汇览:有 summary_markdown 时渲染 markdown,否则 fallback 到现有 vv-recog-line
- 分镜脚本区:新增文案预览区渲染 copy_display_markdown,编辑交互不变
- types 补充 summary_markdown / copy_display_markdown 字段
- 新增 vv-md-body markdown 排版样式
2026-10-07 19:24:43 +08:00
CI Bot 77e19a6b44 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m19s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m37s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m5s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m31s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m31s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m40s
AI Code Review / AI Code Review (pull_request) Successful in 7m5s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m22s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 14m19s
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) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m39s
2026-10-07 11:07:14 +00:00
Xiaoxia Agent e4c3f9a046 ci: re-trigger CI pipeline
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m14s
CI/CD Pipeline / Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-07 19:02:34 +08:00
Xiaoxia Agent 902effc1f9 feat: 提示词控制展示格式 - summary_markdown + copy_display_markdown
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 3s
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 / 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m33s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m32s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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
- assembler.py: 新增 _build_summary_markdown 兜底函数,VLM未返回时根据结构化字段生成markdown
- reviewer.py: markdown展示字段不参与合规审核(避免格式字符误判)
- viral_video.py: _script_from_xml 提取 copy_display_markdown 字段
- migration 104: v8 image_analysis prompt(新增summary_markdown输出要求)+ v3 storyboard prompt(新增copy_display_markdown输出要求)
- v8/v3 设为active,v7/v2 停用
2026-10-07 18:45:39 +08:00
CI Bot a408cfdc97 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 / 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 12s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 13s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 12s
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 / Frontend Lint (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 / 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 / Deploy Staging (Watchtower auto-deploy) (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 / Check push changed paths (push) Successful in 49s
CI/CD Pipeline / Staging E2E Tests (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 / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m2s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m58s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m29s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m21s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m27s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Integration Tests (push) Successful in 5m6s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m43s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 5m21s
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 6m16s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m34s
AI Code Review / AI Code Review (pull_request) Successful in 7m10s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 8m1s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m21s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m2s
CI/CD Pipeline / Validate - Security (push) Successful in 11m9s
CI/CD Pipeline / Unit Tests (push) Failing after 12m30s
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 / Build Production API 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 25m16s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-07 09:46:34 +00:00
xiaoxia 9464322710 Merge pull request 'fix: PR#2233 followup - 修复3个线上bug' (#2234) from fix/pr2233-followup into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 15s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 8s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m18s
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 / 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 / PR Build API Image (pull_request) Successful in 1m35s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m54s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / Retag skipped Staging Worker 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 / 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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 5m48s
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 / Validate - Python (mypy + alembic) (push) Successful in 7m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m22s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m38s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
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 / Unit Tests (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 / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
2026-10-07 17:37:26 +08:00
xiaoxia aa1f318308 feat(lipsync): 对接蚂蚁 Ditto 数字人 API 替换 MuseTalk 口型(#2076) (#2235)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
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 / 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 (push) Successful in 24s
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 Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 40s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API 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 - Python (mypy + alembic) (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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web 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 / 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 cancelled
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 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 / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-07 17:35:58 +08:00
Xiaoxia Agent 3a59948f53 fix: PR#2233 followup - 修复3个线上bug
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m7s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m26s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m16s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m2s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m3s
AI Code Review / AI Code Review (pull_request) Successful in 7m0s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 10m17s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m27s
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 / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m27s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 45s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 49s
Bug1: ai_client.py 日志格式化TypeError
- timeout=%d 改为 timeout=%s
- 传 getattr(_req_timeout, "read", _req_timeout) 提取数值

Bug2: assembler.py store分支name兜底太激进
- 门头图name不再用brand(避免与brand字段重复显示)
- store_type有具体值时用store_type
- store_type为默认"店铺"时用"门店门头"

Bug3: reviewer超时后未正确降级放行
- reviewer.py: LLM审核失败时返回passed=True(降级放行)
- reviewer.py: _llm_review加try/except捕获异常返回None
- viral_video.py: passed=False但issues为空时(超时导致),降级放行

分支: fix/pr2233-followup
2026-10-07 17:21:19 +08:00
xiaoxia 3e6f87a8b5 Merge pull request 'fix: 脚本超时优化 + 主题智能匹配' (#2233) from fix/script-generation-timeout-and-theme into develop
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 2s
CI/CD Pipeline / PR Build Web Image (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 / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (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 / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (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 / Check push changed paths (push) Successful in 27s
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 1m14s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m21s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m55s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m26s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m35s
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 4m16s
CI/CD Pipeline / Validate - Style (push) Successful in 4m42s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m28s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m7s
AI Code Review / AI Code Review (pull_request) Successful in 7m7s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m52s
CI/CD Pipeline / Integration Tests (push) Successful in 7m57s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m29s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m42s
CI/CD Pipeline / Validate - Security (push) Successful in 10m33s
CI/CD Pipeline / Unit Tests (push) Failing after 11m16s
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 / Build Production Web 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-07 16:56:49 +08:00
Xiaoxia Agent 5da46945fa fix: 脚本超时优化 + 主题智能匹配
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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 58s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m55s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m6s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m34s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m9s
AI Code Review / AI Code Review (pull_request) Successful in 6m39s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m11s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m59s
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 / Canary Release to Production (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 / CI Gate (pull_request) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m59s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 44s
问题A - 超时优化:
1. DoubaoClient httpx timeout 改为显式 Timeout(connect=10, read=T, write=10, pool=5)
2. intent_parsing 单次超时 60s→20s
3. copy_review(reviewer) 添加 timeout=25s
4. 脚本 fast_timeout 150→90s, pro_timeout 150→60s
5. _step_intent_parsing 加 60s 总 deadline
6. _step_script_generation 加 180s 总 deadline
7. lite/fallback 模型与 primary 相同时跳过重复调用

问题B - 主题匹配:
1. 新增 _determine_theme() 根据图片类型+营销目的智能推断主题
2. _fallback_script 动态主题+对应口播文案
3. _empty_copy_result/_validate_and_normalize/_script_from_xml 去除硬编码好物分享
4. intent_parsing prompt 注入 marketing_purpose 和 image_category_hint
5. storyboard prompt 增加主题匹配指导

分支: fix/script-generation-timeout-and-theme
2026-10-07 16:43:59 +08:00
xiaoxia bff20b03d7 Merge pull request 'fix: 门店图partial截断brand兜底 + fast_elapsed计时修复' (#2232) from fix/vision-v7-partial-brand-and-timeout into develop
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 / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (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 / Frontend Lint (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 / PR Build Web Image (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 / Check push changed paths (push) Successful in 24s
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 1m0s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m14s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m28s
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 / PR Build Worker Image (pull_request) Successful in 3m33s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m38s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m39s
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 / Integration Tests (push) Successful in 4m58s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m18s
CI/CD Pipeline / Validate - Style (push) Successful in 5m51s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m45s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m58s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m53s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m37s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m50s
CI/CD Pipeline / Validate - Security (push) Successful in 10m25s
AI Code Review / AI Code Review (pull_request) Successful in 11m48s
CI/CD Pipeline / Unit Tests (push) Failing after 12m23s
CI/CD Pipeline / Build Production Worker 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 API 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-07 16:06:57 +08:00
Xiaoxia Agent 63c8496fa8 fix: 门店图partial截断brand兜底 + fast_elapsed计时修复
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m9s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m44s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m22s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m7s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m39s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m48s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m49s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m10s
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 / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m8s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 33s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m11s
Bug1 - assembler store分支brand多级兜底:
- brand_signage为空/无法判断时,从visible_text找招牌/门头位置文字
- 其次从text_on_package找2-8字非描述性短词
- 都没有才fallback到无法判断
- name兜底:store_type为空时用brand替代

Bug2 - fast_path.py计时修复:
- 将ThreadPoolExecutor从with语句改为显式shutdown(wait=False)
- fast_elapsed在finally块中计算,避免等待未完成线程导致计时膨胀
- 确保_fast_elapsed只反映fast路径实际尝试时间(≤20s),不包含pro兜底
2026-10-07 15:35:38 +08:00
auto-approve-bot 99ba9b7c58 Merge pull request 'fix: 爆款视频图片分析链路全面加固(tokens扩容/JSON容错/pro模型/精简prompt)' (#2231) from fix/vision-v6-robustness-overhaul into develop
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 2s
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 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 / 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 / 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 / Check push changed paths (push) Successful in 25s
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 1m6s
Preview Deploy / Deploy Preview Environment (pull_request) 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 / 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 1m54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m59s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m3s
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
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 / Integration Tests (push) Successful in 4m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m17s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m58s
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 4m50s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m16s
AI Code Review / AI Code Review (pull_request) Successful in 6m59s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m3s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m37s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m42s
CI/CD Pipeline / Validate - Security (push) Successful in 8m42s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m20s
CI/CD Pipeline / Unit Tests (push) Failing after 11m20s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-07 15:05:26 +08:00
Xiaoxia Agent ef82192679 fix: review修复 - ai_client扩容改2.0x + last_finish_reason + fast路径改回primary
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 / 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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m28s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m59s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m12s
AI Code Review / AI Code Review (pull_request) Successful in 6m38s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m35s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m18s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m5s
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 / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m17s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 32s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 5m3s
- ai_client: chat/vision_completion finish_reason=length 扩容从1.5x改为2.0x
- ai_client: 新增 self.last_finish_reason 属性,每次调用成功后记录
- vlm_fast_json: variant从lite改回primary(lite_model和primary相同无意义)
- pro路径保持variant=fallback(qwen3.7-plus),实现真正的fast/pro模型差异化兜底
2026-10-07 14:51:15 +08:00
CI Bot 0bd4123ae5 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / 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 / 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m0s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m3s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m7s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m34s
AI Code Review / AI Code Review (pull_request) Successful in 6m46s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m0s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m41s
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 / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m45s
2026-10-07 06:36:24 +00:00
Xiaoxia Agent 9139c697b0 feat: 更新v7 prompt为用户确认版本
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m40s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m44s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m49s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 4m27s
CI/CD Pipeline / PR Build API Image (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- 采用纯中文自然语言风格(#角色/#任务/##技能/##限制)
- type字段值改为英文(product/store/person/scene/other)以匹配assembler路由
- JSON key保持英文,描述使用中文+举例
- 移除JSON示例,依赖response_format=json_object保证输出格式
- 保留6技能架构:类型判断/通用信息/门店/商品/人物/风景
- max_tokens 3000、max_retries 3、fallback variant=fallback等配置保持不变
2026-10-07 14:31:48 +08:00
Xiaoxia Agent b60de7202a fix: vision编排恢复develop骨架并精准加固(lite/fallback variant、json_utils双重解析、超时20/45)
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m2s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m13s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m26s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m15s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 3m50s
AI Code Review / AI Code Review (pull_request) Successful in 6m38s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m43s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 7m18s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m0s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m6s
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 / CI Gate (pull_request) Failing after 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 3m37s
2026-10-07 14:04:35 +08:00
Xiaoxia Agent f1bd816449 fix: 修正vlm模块router导入(单例名为ai_router,无get_ai_router函数)
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 57s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m22s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m29s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m48s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m50s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 6m3s
AI Code Review / AI Code Review (pull_request) Successful in 6m35s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m2s
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 / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m13s
此前导入get_ai_router导致单测collection失败、运行时ImportError。
2026-10-07 13:48:02 +08:00
CI Bot 249b70e53e style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / Check if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m11s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 3m40s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m3s
AI Code Review / AI Code Review (pull_request) Successful in 6m39s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 7m57s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 9m29s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 6m29s
2026-10-07 05:35:15 +00:00
Xiaoxia Agent dbc6db02e0 fix: 103迁移增加ai_capability_configs表存在性守卫
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 / 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 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 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 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m14s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m59s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m19s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m25s
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
全新alembic-only库该表由create_all创建可能不存在,
导致Validate-Python/Integration全新库迁移失败(同102处理方式)
2026-10-07 13:30:18 +08:00
Xiaoxia Agent ec28699806 fix: 爆款视频图片分析链路全面加固(tokens扩容/JSON容错/pro模型/精简prompt)
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 if frontend-only change (pull_request) Successful in 1s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Failing after 2m37s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m16s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 4m0s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m4s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m32s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m38s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 7m0s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
8项修复:
1. ai_client: max_retries默认3, finish_reason=length时2.0x扩容重试,
   暴露last_finish_reason
2. 新增vision/json_utils.py: markdown剥离/括号切片/控制字符清理/
   截断JSON括号栈补全/尾部截断重试, partial产物带_partial标记
3. vlm_fast_json/vlm_fallback: 接入json_utils + 本层2次整请求重试,
   非JSON幻觉文本二次提示, partial返回
4. migration103: image_analysis max_tokens 1500→3000, max_retries 1→3
5. pro fallback: variant=fallback(此前误用primary主模型),
   max_tokens=4000, temp=0.3, 超时45s; ai_router修复fallback variant解析
6. v7精简prompt(~1KB, v6 ~4.5KB)插入并激活, v6停用保留
7. assembler: partial碎片兜底填充空字段, product截断空products改路由,
   furnishings支持dict子对象, v6全字段审计
8. fast_path: FAST 20s/PRO 45s, 空壳JSON检测回退

Closes #2266
2026-10-07 13:22:20 +08:00
auto-approve-bot afc7a37d17 Merge pull request 'fix: _assemble_v4路由优先级修复,scene/store有人物时不再误入person分支' (#2230) from fix/assembler-v4-routing-priority into develop
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 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 / 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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (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 32s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m15s
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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m46s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m51s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m39s
CI/CD Pipeline / Validate - Style (push) Successful in 4m10s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m51s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m34s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m43s
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 / Frontend Unit Tests (push) Successful in 5m52s
AI Code Review / AI Code Review (pull_request) Successful in 6m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m3s
CI/CD Pipeline / Validate - Security (push) Successful in 7m41s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m54s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 2m28s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m7s
CI/CD Pipeline / Integration Tests (push) Successful in 9m39s
CI/CD Pipeline / Unit Tests (push) Failing after 17m39s
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-07 12:34:17 +08:00
Xiaoxia Agent 731ad37217 fix: _assemble_v4路由优先级修复,scene/store有人物时不再误入person分支
CI/CD Pipeline / Check push changed paths (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 / 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 / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (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 / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m36s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m11s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m30s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 3m58s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m50s
AI Code Review / AI Code Review (pull_request) Successful in 6m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m38s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 7m16s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m35s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 4m16s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 32s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 39s
问题:person分支条件 vtype==person or has_person 过于宽泛,
当v6 prompt返回type=scene/store但画面有人时,has_person=true
导致直接进入person分支,scene/store的专有字段全部丢失。

修复:
1. person分支条件收窄为 vtype==person,去掉 or has_person
2. 新增向后兼容逻辑:type不在已知枚举时按has_person/products兜底
3. scene/store分支has_person=true时,提取人物穿着/姿势等信息
   追加到key_features(前缀人物:),不丢失人物数据
4. store返回的has_person字段改为反映真实值

Closes #2265
2026-10-07 12:22:09 +08:00
xiaoxia c551ecbcc5 Merge pull request 'fix: 修复僵尸任务误杀竞态 & resume方法重置时间戳' (#2229) from fix/stale-job-race-resume-timestamp into develop
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 / 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 4s
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 if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 25s
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 40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 42s
CI/CD Pipeline / Build Staging API Image (push) Successful in 41s
CI/CD Pipeline / Retag skipped Staging 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 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 Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m52s
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 / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 25s
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 / Staging E2E Tests (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 37s
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 3m13s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m15s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m50s
CI/CD Pipeline / Integration Tests (push) Successful in 3m54s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m58s
CI/CD Pipeline / Validate - Style (push) Successful in 5m1s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m21s
AI Code Review / AI Code Review (pull_request) Successful in 6m48s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m44s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m28s
CI/CD Pipeline / Validate - Security (push) Successful in 8m36s
CI/CD Pipeline / Unit Tests (push) Failing after 14m18s
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 / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
fix(P0): resume方法无条件重置started_at/heartbeat_at + _recover_stale_jobs加updated_at防御,修复用户等待超10分钟后点生成文案被误杀的竞态bug
2026-10-07 11:55:46 +08:00
Xiaoxia Agent 873fa89305 fix: 修复僵尸任务误杀竞态 & resume方法重置时间戳
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 0s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m46s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m26s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 4m19s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m26s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m27s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m12s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m4s
AI Code Review / AI Code Review (pull_request) Successful in 7m7s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 3m29s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m13s
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
问题:用户在图片分析完成10分钟以上后点击生成文案,
任务被 _recover_stale_jobs 误判为僵尸任务并杀掉。
根因:resume_from_image_analyzed 未重置 started_at/heartbeat_at,
首次进入 RUNNING 时沿用 stage1 的旧时间戳(35分钟前),
触发 stale job 回收条件(started_at > 10min 且 heartbeat_at > 2min)。

修复:
1. packages/domain/viral_video.py:
   - resume_from_image_analyzed / resume_from_copy_generated /
     resume_from_confirm 三个方法无条件重置
     started_at=now 和 heartbeat_at=now
   - _is_regen 分支的 heartbeat_at=None 先清零再统一赋新值,
     保证所有路径进入 RUNNING 后时间戳都是最新的

2. apps/api/.../viral_video.py:retry endpoint 已确认
   在设置 status=PENDING 后同时清空 started_at 和 heartbeat_at
   (无需额外修改)

3. apps/worker/.../viral_video.py:_recover_stale_jobs SQL
   增加 updated_at < :cutoff_beat 作为核心防护条件,
   确保近期有活动(心跳/状态更新)的任务不会被误回收

无数据库迁移,纯 Python 修改。

Closes #2264
2026-10-07 11:49:47 +08:00
xiaoxia 225406cc2e Merge pull request 'feat: assembler适配v6 prompt(store/scene类型+environment_objects)+ migration102 image_analysis max_tokens 1500' (#2228) from feature/v6-prompt-assembler-store-scene into develop
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 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 28s
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 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 / 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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m17s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m24s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 3m31s
PR Automation / Auto Merge on CI Green + Approved (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 API Image (pull_request) Successful in 4m10s
CI/CD Pipeline / Build Staging API Image (push) Successful in 4m4s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m59s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m12s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m5s
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
AI Code Review / AI Code Review (pull_request) Successful in 5m37s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m16s
CI/CD Pipeline / Integration Tests (push) Successful in 7m20s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m1s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 8m38s
CI/CD Pipeline / Validate - Security (push) Successful in 9m41s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m19s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m36s
CI/CD Pipeline / Unit Tests (push) Failing after 12m46s
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-07 11:39:06 +08:00
CI Bot 4ccb395dd1 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m15s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m38s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m19s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m42s
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m3s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m11s
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m8s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 29s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 7m28s
2026-10-07 03:23:56 +00:00
Xiaoxia Agent f5162455c2 feat: assembler适配v6 prompt新增字段(store/scene类型+environment_objects)+ migration102 image_analysis max_tokens提到1500
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m2s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m9s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m27s
AI Code Review / AI Code Review (pull_request) Successful in 6m46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 8m3s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m50s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-07 11:13:17 +08:00
xiaoxia 5b4b844f1a Merge pull request 'fix(P0): 图片分析max_tokens硬编码截断JSON + 补qwen-vl-plus migration101' (#2227) from feature/fix-vlm-max-tokens-qwen-vl-plus into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
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 Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web 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 / Check push changed paths (push) Successful in 27s
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 1m6s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m18s
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 2m16s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m16s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m24s
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 3m14s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m49s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m34s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m31s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m39s
AI Code Review / AI Code Review (pull_request) Successful in 7m18s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m5s
CI/CD Pipeline / Integration Tests (push) Successful in 14m54s
CI/CD Pipeline / Validate - Style (push) Successful in 16m17s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 20m6s
CI/CD Pipeline / Unit Tests (push) Failing after 23m0s
CI/CD Pipeline / Validate - Security (push) Successful in 38m53s
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
Merge PR #2227: qwen-vl-plus模型绑定+max_tokens去硬编码+自动扩容重试
2026-10-06 22:55:05 +08:00
CI Bot 587eefd8fa style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (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 (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 Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 55s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m24s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m1s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m3s
AI Code Review / AI Code Review (pull_request) Successful in 8m39s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 13m27s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m51s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 14m3s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 17m27s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 20m41s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 36m1s
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 / Build Production Web 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) Failing after 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 34s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m6s
2026-10-06 14:16:04 +00:00
Xiaoxia Agent cbc9fc885b fix: migration101将capability max_tokens默认值更新移至image_analysis逻辑前,避免return跳过
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 / 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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m25s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m0s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m2s
AI Code Review / AI Code Review (pull_request) Successful in 7m9s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m40s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 15m46s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 20m20s
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
2026-10-06 21:54:12 +08:00
Xiaoxia Agent 1fb156745d fix(P0): finish_reason=length自动1.5x扩容重试 + migration101补全各capability max_tokens默认值
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 1s
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 (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 / 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m16s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m50s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m53s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m41s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 14m14s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 17m11s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 20m20s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 36m7s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
2026-10-06 21:12:16 +08:00
CI Bot 607e989b95 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Build Staging Worker Image (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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 50s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m12s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
AI Code Review / AI Code Review (pull_request) Successful in 7m0s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m45s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m40s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 15m47s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 16m24s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 23m48s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 34m42s
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) Failing after 2s
2026-10-06 12:31:09 +00:00
Xiaoxia Agent c277e87ad3 fix(P0): 图片分析max_tokens改DB配置 + migration101补qwen-vl-plus
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 if frontend-only change (pull_request) Successful in 2s
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 / Build Staging Web Image (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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 48s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m47s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m35s
CI/CD Pipeline / Validate - Python (mypy + alembic) (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m36s
问题:qwen-vl-plus图片识别返回JSON约500-600 tokens,vlm_fast_json硬编码
max_tokens=350导致JSON截断解析失败返回未识别。staging已临时验证1000可用。

- ai_client: vision_completion/chat_completion max_tokens默认值改None,
  None时使用self.max_tokens(构造函数从cap DB配置传入),硬编码仅作兜底
- vlm_fast_json/vlm_fallback: 删除_DEFAULT_MAX_TOKENS硬编码,调用时不传
  max_tokens,保留可选覆盖参数;更新文件头为qwen-vl-plus
- migration 101: 幂等插入qwen-vl-plus模型;仅当image_analysis当前primary
  不是qwen-vl-plus时才更新primary/lite绑定、fallback=qwen3.7-plus、
  max_tokens=1000,避免覆盖后台手动配置
2026-10-06 20:17:17 +08:00
xiaoxia c25269051e Merge pull request 'fix(P0): DoubaoClient vision_completion模型字段错误 + provider-specific fallback' (#2226) from feature/fix-vlm-401-provider-fallback into develop
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 3s
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 / 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 / Check push changed paths (push) Successful in 28s
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 34s
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 Staging API Image (push) Successful in 56s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m2s
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 / Build Staging Worker Image (push) Successful in 40s
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m7s
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 3m20s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m44s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m20s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 6m11s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m37s
AI Code Review / AI Code Review (pull_request) Successful in 7m17s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m54s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m46s
CI/CD Pipeline / Integration Tests (push) Successful in 12m47s
CI/CD Pipeline / Validate - Style (push) Successful in 13m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 16m37s
CI/CD Pipeline / Unit Tests (push) Failing after 21m17s
CI/CD Pipeline / Validate - Security (push) Successful in 33m52s
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
Fix: vision_completion uses self.model + provider-aware fallback (#2226)
2026-10-06 19:48:36 +08:00
Xiaoxia Agent 54842c1387 fix(P0): DoubaoClient vision_completion使用self.model + 构造函数按provider区分fallback
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 if frontend-only change (pull_request) Successful in 2s
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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 52s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m59s
AI Code Review / AI Code Review (pull_request) Successful in 6m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m55s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m56s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m42s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 13m47s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 31s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 18m34s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 5m41s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 33m20s
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 / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Bug 1(致命):vision_completion payload使用self.vision_model(settings硬编码
豆包视觉模型名),而非构造函数传入的self.model。dashscope provider下发送
豆包模型名到dashscope端点导致404/401。

Bug 2(重要):构造函数api_key/model/base_url为空时一律fallback到doubao
(火山引擎)配置。provider=dashscope时应fallback到dashscope配置,否则
dashscope key请求火山方舟地址返回401。

TTSClient/ImageGenClient/VideoGenClient为纯数据持有者,无fallback逻辑,
无需修改。
2026-10-06 19:30:37 +08:00
xiaoxia d1c137af8a Merge pull request 'fix: AI路由层收尾修复 - 清除fallback硬编码 + migration 100修正模型绑定' (#2225) from feature/ai-model-router-db-config into develop
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 (push) Successful in 1s
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 / 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 / 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 - 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 / PR Build Web Image (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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 22s
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 / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) 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 1m8s
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 1m28s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m7s
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 / Build Staging Worker Image (push) Successful in 3m38s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m17s
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 5m6s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m9s
AI Code Review / AI Code Review (pull_request) Successful in 7m10s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m46s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m20s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 8m56s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 10m13s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m27s
CI/CD Pipeline / Validate - Security (push) Successful in 11m12s
CI/CD Pipeline / Unit Tests (push) Failing after 11m38s
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 / 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
CI/CD Pipeline / Integration Tests (push) Successful in 14m7s
CI/CD Pipeline / CI Gate (push) Has been skipped
2026-10-06 18:27:48 +08:00
Xiaoxia Agent f0eaf4c31f fix: remove hardcoded defaults from fallback methods and add migration 100
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 if frontend-only change (pull_request) Successful in 2s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m28s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m27s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m19s
AI Code Review / AI Code Review (pull_request) Successful in 6m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m51s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m46s
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) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m51s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 28s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m7s
- ai_router.py: replace hardcoded URLs and model names with empty strings
  in _fallback_tts_client, _fallback_image_gen_client, _fallback_video_gen_client
- cosyvoice_service.py: replace hardcoded cosyvoice_clone_model default
- alembic: add migration 100 to fix capability model bindings (idempotent)
2026-10-06 18:09:42 +08:00
xiaoxia a8a20d6f87 fix(viral-video): 修复「重新生成文案」返回 409 的问题 (#2223)
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 5s
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 5s
CI/CD Pipeline / Check if frontend-only change (pull_request) 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 / Check push changed paths (push) Successful in 27s
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 / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Unit 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 / PR Build API Image (pull_request) Successful in 31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 48s
CI/CD Pipeline / Build Staging API Image (push) Successful in 37s
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 / CI Gate (pull_request) Successful in 2s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m45s
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 4m39s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m43s
CI/CD Pipeline / Validate - Style (push) Successful in 4m53s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m8s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m23s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m42s
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) Successful in 1m7s
AI Code Review / AI Code Review (pull_request) Successful in 6m40s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m41s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m43s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m15s
CI/CD Pipeline / Validate - Security (push) Successful in 12m35s
CI/CD Pipeline / Unit Tests (push) Failing after 12m33s
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-06 16:30:01 +08:00
xiaoxia 0fa2397f33 fix(viral-video): 文案区域固定高度+内部滚动,按钮固定框底 (#2222)
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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 3s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
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 / Check push changed paths (push) Successful in 7s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) 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 / Frontend Lint (push) 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
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 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 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
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (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 / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (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 / 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
AI Code Review / AI Code Review (pull_request) Has been cancelled
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
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-06 16:29:10 +08:00
xiaoxia 52e757f227 Merge pull request 'feat: AI模型路由层 — 统一模型配置读取与客户端构建(零硬编码)' (#2220) from feature/ai-model-router-db-config into develop
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 / Frontend Lint (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 / 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 3s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
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 / Check push changed paths (push) Successful in 27s
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 56s
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 / 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 1m2s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 38s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 56s
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
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m14s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m15s
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 / PR Build Worker Image (pull_request) Successful in 4m20s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m48s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Validate - Style (push) Successful in 4m58s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m14s
CI/CD Pipeline / Integration Tests (push) Successful in 6m33s
AI Code Review / AI Code Review (pull_request) Successful in 7m6s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m59s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m14s
CI/CD Pipeline / Validate - Security (push) Successful in 10m18s
CI/CD Pipeline / Unit Tests (push) Failing after 12m12s
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-06 16:11:09 +08:00
xiaoxia 8d4ad83212 chore: retrigger CI for staging redeploy
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 3s
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 / 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 / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit 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 / 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 / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 25s
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 / PR Build API Image (pull_request) Successful in 1m3s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m9s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m4s
CI/CD Pipeline / CI Gate (pull_request) Successful in 8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m49s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m26s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 4m0s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m13s
CI/CD Pipeline / Validate - Style (push) Successful in 4m39s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m39s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m21s
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) Successful in 1m11s
AI Code Review / AI Code Review (pull_request) Successful in 6m56s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m48s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m56s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m36s
CI/CD Pipeline / Validate - Security (push) Successful in 9m45s
CI/CD Pipeline / Unit Tests (push) Failing after 14m24s
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-06 15:51:10 +08:00
Xiaoxia Agent 92bacf3853 fix: remove duplicate except block in viral_video.py storyboard section
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
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 1m10s
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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m2s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m7s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m9s
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 7m21s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 7m30s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m26s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m36s
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 / Build Production Web 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 / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m35s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 51s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m9s
2026-10-06 15:31:56 +08:00
Xiaoxia Agent 8f949ae5d8 refactor: PR#2220 review fixes — DoubaoClient accepts DB config, remove redundant client wrappers
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 3s
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 / Build Staging Web Image (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 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 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 / ACR Image Cleanup (pull_request) Has been skipped
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (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 / Integration Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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
1. DoubaoClient.__init__() now accepts explicit params (api_key, base_url, model, etc.)
   so AIRouter can inject DB-sourced config instead of DoubaoClient reading settings itself.
   Added provider field, **kwargs on chat_completion/vision_completion for extra params.

2. ai_router.py: Removed LLMClient/VisionClient classes. _build_llm_client() and
   _build_vision_client() now return DoubaoClient instances directly. Kept simple
   TTSClient/ImageGenClient/VideoGenClient wrappers. Fixed all fallback methods to
   read from settings instead of hardcoding URLs/model names.

3. viral_video.py: Intent parsing and storyboard sections now use ai_router.get_llm_client()
   to get DoubaoClient instances directly, instead of manually extracting model_key and
   passing to a shared _llm_client.

4. vision/vlm_fast_json.py & vlm_fallback.py: Now use ai_router.get_vision_client()
   to get DoubaoClient and call vision_completion() with **kwargs (enable_thinking,
   response_format), instead of building their own httpx requests.

5. tests: Updated test_ai_router.py to mock DoubaoClient import (avoiding Python 3.10
   compatibility chain), removed LLMClient/VisionClient references, added vision_completion check.
2026-10-06 15:30:27 +08:00
Xiaoxia Agent ed118d4444 fix: 修复cosyvoice/tts_service测试mock配置 - ai_router.get_tts_client返回None避免MagicMock穿透 - 修复test_tts_service_factory缺少MagicMock导入
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 if frontend-only change (pull_request) Successful in 1s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 49s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m28s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m32s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m24s
AI Code Review / AI Code Review (pull_request) Successful in 6m35s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 7m3s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m45s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 12m45s
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 / Build Production Web 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) Failing after 2s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m51s
2026-10-06 14:55:13 +08:00
Xiaoxia Agent 5a5833166a fix: tts_service_factory test patch path
CI/CD Pipeline / Check push changed paths (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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 9s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 11s
CI/CD Pipeline / Retag skipped Staging Web Image (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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m8s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m8s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m23s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m36s
AI Code Review / AI Code Review (pull_request) Successful in 6m58s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 11m5s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m59s
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 / Canary Release to Production (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 / CI Gate (pull_request) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m3s
2026-10-06 14:40:06 +08:00
Xiaoxia Agent b3e97e6bae fix: 修正测试patch路径
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 / 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 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 cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (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 / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-06 14:39:42 +08:00
CI Bot 6b20a568ec style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 Lint (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 51s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m1s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m38s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m3s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m6s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m59s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m10s
AI Code Review / AI Code Review (pull_request) Successful in 6m51s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 10m7s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m21s
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 / CI Gate (pull_request) Failing after 1s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m23s
2026-10-06 14:21:23 +08:00
Xiaoxia Agent b429117e97 chore: remove backup file 2026-10-06 14:21:23 +08:00
Xiaoxia Agent 4000a81f91 fix: 修复测试用例以适配ai_router改造
- test_config_base.py: cosyvoice_clone_model默认值改为空串
- test_cosyvoice_service.py: mock ai_router避免DB查询
- test_tts_service_factory.py: mock get_shared_settings确保正确fallback
2026-10-06 14:21:23 +08:00
CI Bot b32a14ada6 style: auto-format with black + isort + ruff + prettier [skip ci-format-check] 2026-10-06 14:21:23 +08:00
Xiaoxia Agent d0ff504a5f feat: AI模型路由层 — 统一模型配置读取与客户端构建
核心改动:
- packages/shared/ai_config_version.py: Redis版本号通知机制
- packages/shared/ai_router.py: AIRouter统一路由层(DB→Redis缓存→SharedSettings fallback)
- alembic/versions/099: 补齐缺失模型seed和capability配置
- apps/worker/worker_app/tasks/vision/*: VLM硬编码替换为ai_router动态配置
- packages/application/viral_video/reviewer.py: 审核走copy_review capability
- packages/application/cosyvoice_service.py: TTS走tts capability
- apps/worker/worker_app/tasks/viral_video.py: 意图解析/分镜/文案走DB配置
- packages/config/base.py: 移除doubao/dashscope/mediakit/cosyvoice硬编码默认值
- tests/unit/test_ai_router.py: 26个单元测试覆盖路由/缓存/fallback

Admin侧:
- app/utils/ai_config_notify.py: bump_ai_config_version()工具函数
- routers/ai_models.py + ai_capability_configs.py: CRUD后调用bump_version()

验收标准:
- admin改模型后30s内生效(Redis版本号通知)
- Redis故障fallback环境变量
- base.py零硬编码(api_key保留空串)
- 26个单测全绿
2026-10-06 14:21:23 +08:00
CI Bot 498fe7b38c 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 if frontend-only change (pull_request) Successful in 2s
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 / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (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 / 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 push changed paths (push) Successful in 10s
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 / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 55s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m9s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 36s
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 / ACR Image Cleanup (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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m23s
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
CI/CD Pipeline / Integration Tests (push) Successful in 4m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m52s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m12s
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 / Validate - Style (push) Successful in 5m29s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Failing after 40s
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m33s
AI Code Review / AI Code Review (pull_request) Successful in 7m9s
CI/CD Pipeline / Validate - Security (push) Successful in 10m39s
CI/CD Pipeline / Unit Tests (push) Failing after 14m45s
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 / Build Production API 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-06 06:05:04 +00:00
xiaoxia 4266f4a6a2 fix(viral-video): 信任链只替换人像图,场景/商品图保留原图 (#2221)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 3s
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 12s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (push) Successful in 1m43s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m28s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m37s
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 / 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 API Image (pull_request) Successful in 34s
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 / Build Staging API Image (push) Successful in 2m3s
CI/CD Pipeline / Integration Tests (push) Successful in 5m2s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m16s
AI Code Review / AI Code Review (pull_request) Successful in 7m15s
PR Automation / Auto Merge on CI Green + Approved (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 / 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 / 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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m5s
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 / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (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 / 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 / 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 / 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 / Frontend Unit Tests (push) Has been cancelled
2026-10-06 13:52:38 +08:00
xiaoxia a50cbc995f fix(viral-video): render流程禁止补生成意图/编导脚本 (#2219) (#2219)
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 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
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 / 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 / Check push changed paths (push) Successful in 23s
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 1m10s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m12s
CI/CD Pipeline / Staging E2E Tests (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 / Staging API Integration Tests (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 1m11s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m48s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 32s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m20s
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) Failing after 31s
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m16s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m39s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m46s
CI/CD Pipeline / Validate - Style (push) Successful in 4m18s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m52s
AI Code Review / AI Code Review (pull_request) Successful in 6m48s
CI/CD Pipeline / Validate - Security (push) Successful in 7m33s
CI/CD Pipeline / Unit Tests (push) Failing after 11m49s
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
fix(viral-video): render流程禁止补生成意图/编导脚本 (#2218)
2026-10-06 12:18:56 +08:00
xiaoxia cfca2443c4 Merge pull request 'feat(vision): 人物图片分析质量提升 v5(assembler字段扩充+migration 098 seed)' (#2218) from feature/vision-v5-person-quality into develop
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 / 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 3s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
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 - 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 / 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 / Check push changed paths (push) Successful in 30s
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 Web 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 1m26s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m31s
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 / Build Staging API Image (push) Successful in 1m22s
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 / CI Gate (pull_request) Successful in 10s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m31s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 2m55s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m46s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m56s
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 / Integration Tests (push) Successful in 3m31s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m42s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 4m13s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m37s
CI/CD Pipeline / Validate - Security (push) Successful in 6m44s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m9s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m50s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m7s
AI Code Review / AI Code Review (pull_request) Successful in 10m4s
CI/CD Pipeline / Unit Tests (push) Failing after 11m28s
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-06 10:56:08 +08:00
CI Bot 6cb9cf0b27 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 if frontend-only change (pull_request) Successful in 2s
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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m28s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m17s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m36s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m53s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m16s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 4m51s
AI Code Review / AI Code Review (pull_request) Successful in 6m37s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10m36s
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 / Build Production Web 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) Failing after 1s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 7m28s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 30s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m9s
2026-10-06 10:43:35 +08:00
Xiaoxia Agent b8c6091a11 feat(vision): 人物图片分析质量提升 v5
- assembler 新增 v5 人物 schema 支持:扩充 shoes/bag/outerwear/makeup/shot_type/lighting/atmosphere 等字段消费,key_features 上限从6扩到8,appearance 更丰富
- 保留旧扁平 schema 兼容(_assemble_old)
- migration 098:固化 v5 JSON prompt(4583字符,27个人物字段)为 seed,幂等写入
- 新增 test_vision_v4_prompt.py 17个测试覆盖 v4/v5 schema 路由
2026-10-06 10:43:35 +08:00
xiaoxia 3b9a3dd426 fix(viral-video): 编导脚本timeout 90→150s pro 120→150s + 修ai_client logger占位符bug (93b3e896)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 7s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
CI/CD Pipeline / Check push changed paths (push) Successful in 1m5s
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 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m30s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m33s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m31s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m28s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 2m43s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m5s
CI/CD Pipeline / Validate - Style (push) Successful in 3m57s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m26s
AI Code Review / AI Code Review (pull_request) Successful in 7m32s
CI/CD Pipeline / Integration Tests (push) Successful in 5m28s
CI/CD Pipeline / Validate - Security (push) Successful in 6m15s
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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) 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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m3s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 9m16s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m22s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m57s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m17s
CI/CD Pipeline / Unit Tests (push) Failing after 15m36s
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 / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-06 10:17:10 +08:00
xiaoxia 617c40e1d4 Merge pull request 'fix(vision): image_analysis prompt XML/JSON冲突修复 + v4 JSON prompt seed' (#2216) from feature/vision-v4-prompt-fix into develop
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 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / PR Build API Image (push) Has been skipped
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 Worker 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 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 / Check push changed paths (push) Successful in 29s
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 Web Image (push) Successful in 33s
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 48s
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 55s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 46s
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 / Frontend Unit Tests (push) Successful in 2m57s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m18s
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 / Integration Tests (push) Successful in 3m48s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m15s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m18s
CI/CD Pipeline / CI Gate (pull_request) Successful in 7s
CI/CD Pipeline / Validate - Style (push) Successful in 5m2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m57s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m34s
AI Code Review / AI Code Review (pull_request) Successful in 6m54s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 5m1s
CI/CD Pipeline / Validate - Security (push) Successful in 8m50s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m47s
CI/CD Pipeline / Unit Tests (push) Failing after 11m6s
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-06 01:24:43 +08:00
Xiaoxia Agent 2597962528 fix(vision): 097 migration裸SQL用sa.text()包裹(SQLAlchemy 2.x要求)
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 0s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m13s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m3s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m39s
AI Code Review / AI Code Review (pull_request) Successful in 6m51s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 7m59s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 10m10s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m42s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 17m21s
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 / Canary Release to Production (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 / CI Gate (pull_request) Successful in 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 33s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 54s
2026-10-06 01:04:30 +08:00
CI Bot 8c56694599 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m38s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m46s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m0s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 4m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 4m15s
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 / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-05 16:59:44 +00:00
Xiaoxia Agent cd618c3f29 fix(vision): image_analysis prompt XML/JSON冲突修复+v4 JSON prompt seed
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (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 / 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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m15s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m37s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 2m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 3m14s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- _prompt: DB有active image_analysis prompt时原样使用,不再追加硬编码schema,
  让DB prompt完全控制输出格式(修复DB写XML、调用强制json_object导致解析失败、
  商品图全部走fallback的问题)
- assembler: 新增v4嵌套schema路由(product/store/person/other四类),
  保留旧扁平schema兼容,下游零改动
- vlm_fallback: pro兜底结果统一走assembler.assemble_result,与fast路径输出一致
- migration 097: 固化staging已验证的v4 JSON prompt并置为active(幂等)
2026-10-06 00:53:58 +08:00
xiaoxia 015fd2c381 fix(viral-video): 修复call_llm传list bug改client.chat_completion + timeout调优fast15/pro30 (80103f8c)
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) 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 21s
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 / 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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m14s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m34s
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 / PR Build API Image (pull_request) Successful in 1m40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m23s
AI Code Review / AI Code Review (pull_request) Successful in 4m48s
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
PR Automation / Auto Merge on CI Green + Approved (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 / 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 / CI Gate (pull_request) Successful in 28s
CI/CD Pipeline / Integration Tests (push) Successful in 4m24s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m27s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m38s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m56s
CI/CD Pipeline / Validate - Style (push) Failing after 6m44s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m33s
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 / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m24s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m24s
CI/CD Pipeline / Validate - Security (push) Successful in 9m28s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m37s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m15s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m40s
CI/CD Pipeline / Unit Tests (push) Failing after 13m9s
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 / Build Production Web 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-06 00:42:57 +08:00
CI Bot 8caf3ac8c3 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 / 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 28s
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 / 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 / PR Build API Image (pull_request) Successful in 49s
CI/CD Pipeline / Build Staging API Image (push) Successful in 32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m42s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 26s
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 / CI Gate (pull_request) Successful in 2s
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 29s
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 3m4s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m18s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m45s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m39s
AI Code Review / AI Code Review (pull_request) Successful in 7m25s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m49s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m53s
CI/CD Pipeline / Integration Tests (push) Successful in 10m1s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 12m13s
CI/CD Pipeline / Validate - Style (push) Failing after 13m53s
CI/CD Pipeline / Unit Tests (push) Successful in 17m8s
CI/CD Pipeline / Validate - Security (push) Successful in 27m42s
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
CI/CD Pipeline / Staging E2E Tests (push) Failing after 35m31s
2026-10-05 15:02:38 +00:00
xiaoxia 3577108e29 fix(vision-v2): 修正prompt解析 删掉开头匹配bug DB有值直接追加JSON schema (5dd12675)
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 (push) Successful in 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m47s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m59s
AI Code Review / AI Code Review (pull_request) Successful in 6m37s
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 (push) Successful in 36s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 32s
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 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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 39s
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 / 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 1m29s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m44s
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 / Frontend Unit Tests (push) Successful in 3m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m58s
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 - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (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 / 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
2026-10-05 22:44:36 +08:00
xiaoxia 0bf4f359a7 Merge pull request 'fix(vision-v2): 恢复后台prompt配置读取,用户自定义提示词生效' (#2211) from fix/vision-v2-db-prompt into develop
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 / 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 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 29s
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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m23s
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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m35s
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 (push) Successful in 23s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m42s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 21s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 45s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
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 / Unit Tests (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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
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 / ACR Image Cleanup (pull_request) Has been cancelled
2026-10-05 22:30:43 +08:00
xiaoxia 35e7789c81 fix(vision-v2): 恢复后台prompt配置读取,修复用户自定义提示词不生效
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 2s
CI/CD Pipeline / Check push changed paths (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 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
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 48s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m7s
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
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m7s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m57s
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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 40s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 11m26s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 11m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 14m6s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 15m2s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 37m14s
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 / CI Gate (pull_request) Failing after 1s
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
根因:#2200重写V2时把 prompt_loader 调用链删了,system/user prompt
全部硬编码在 vlm_fast_json.py / vlm_fallback.py,用户在后台管理端
配置 viral_video_prompt_templates 表 prompt_type='image_analysis' 的
自定义提示词完全没被读取。

修复:
- 新增 vision/_prompt.py,复用 packages.application.viral_video.prompt_loader
  读取后台 image_analysis 配置,30秒TTL热加载
- 判定策略:读到的system_prompt以默认XML模板开头('你是电商商品视觉分析师')
  视为内置默认→使用硬编码JSON schema;否则视为用户自定义→使用用户
  system_prompt并在末尾追加JSON硬约束'你必须只返回一个合法的JSON对象...'
- user_prompt同理:用户模板存在就渲染(image_count=1/industry=通用/image_urls留空),
  不存在用硬编码默认
- DB不可用/读取异常→静默fallback到硬编码JSON prompt,不阻断流程
- fast路径(qwen3.8-flash)和pro路径(qwen3.7-plus)都接入_resolve

本地冒烟:DB不可用时fallback到默认JSON prompt正常;pro兜底返回pp质量良好。

Refs: 用户反馈后台配置提示词无效
2026-10-05 22:29:34 +08:00
xiaoxia 70c526ffc3 Merge pull request 'feat: 功能计费DB化(爆款读配置+对口型/智能剪辑计费)' (#2209) from feature/feature-pricing into develop
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 (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 (push) Successful in 1s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (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 / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 26s
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 / 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 53s
CI/CD Pipeline / Build Staging API Image (push) Successful in 41s
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 / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) 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 / 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 / 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
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
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
2026-10-05 22:28:11 +08:00
Xiaoxia Agent e2de75c9f6 fix(test): 适配#2200/#2207 V2图片分析批处理架构(移除_analyze_single_image断言)
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 1s
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 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 1m4s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m53s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m28s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 11m5s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m47s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m53s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 14m20s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 18m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 27m47s
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 / Build Production Web 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 / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 30s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m58s
2026-10-05 21:55:57 +08:00
Xiaoxia Agent d949e90051 fix(style): E741 模糊变量名 l -> lpos(vision JSON定位)
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m54s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m25s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
AI Code Review / AI Code Review (pull_request) Successful in 7m6s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 9m10s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m13s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m37s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m56s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 16m53s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 23m24s
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 / CI Gate (pull_request) Failing after 2s
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
2026-10-05 21:29:04 +08:00
xiaoxia 7adbb7d331 refactor(vision): #2208 timeout+json_object fix
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 if frontend-only change (pull_request) Successful in 3s
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 / Check push changed paths (push) Successful in 18s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
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 / 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m19s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 29s
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 (push) Successful in 2m44s
CI/CD Pipeline / Build Staging API Image (push) Successful in 29s
AI Code Review / AI Code Review (pull_request) Successful in 6m56s
PR Automation / Auto Merge on CI Green + Approved (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 / 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 / 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 1m30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m16s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m56s
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) Successful in 2m41s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 11m47s
CI/CD Pipeline / Integration Tests (push) Successful in 11m10s
CI/CD Pipeline / Validate - Style (push) Failing after 14m51s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m20s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m40s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m58s
CI/CD Pipeline / Unit Tests (push) Failing after 17m26s
CI/CD Pipeline / Validate - Security (push) Successful in 24m17s
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-05 21:10:04 +08:00
Xiaoxia Agent 8624896379 feat: 功能计费DB化(爆款读配置+对口型/智能剪辑计费)
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (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 / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (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 53s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m52s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m29s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m4s
AI Code Review / AI Code Review (pull_request) Successful in 7m0s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m9s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 13m18s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m27s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 20m25s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
2026-10-05 21:02:35 +08:00
xiaoxia 65343473d8 fix(vision-v2): P0 全部识别失败 - timeout 过短+缺 response_format
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 / 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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m18s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m38s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m24s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m48s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 15m24s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 17m38s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 26m35s
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 / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 21s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m28s
根因:
- _FAST_TIMEOUT/_FAST_JSON_TIMEOUT 设为8s,但qwen3.8-flash关thinking后单图实测8-9s,staging网络稍慢即全部超时
- 超时cancel后走pro兜底,pro timeout=20s也偏紧
- 缺少 response_format=json_object 导致qwen偶发输出中文解释而非JSON

修复:
- fast_json: _DEFAULT_TIMEOUT 8→12s
- fast_path: _FAST_TIMEOUT/_FAST_JSON_TIMEOUT 8→12s, _PRO_TIMEOUT 20→25s
- vlm_fallback: _DEFAULT_TIMEOUT 20→25s
- fast_json + fallback 都加 response_format={'type':'json_object'}强约束JSON输出

本地3图E2E: 8.57s, 3/3 fast_json命中, portrait_prompt正常输出一位年轻男性/女性...

Refs: staging P0 3/3全返回未识别/无法判断
2026-10-05 20:35:40 +08:00
CI Bot d7fa9d9e8d 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 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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 10s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 9s
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 Worker 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 Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 30s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
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 40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m55s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 23s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 36s
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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
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 / 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m3s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m9s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m42s
AI Code Review / AI Code Review (pull_request) Successful in 7m14s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m56s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m49s
CI/CD Pipeline / Integration Tests (push) Successful in 9m41s
CI/CD Pipeline / Validate - Style (push) Failing after 11m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 12m38s
CI/CD Pipeline / Unit Tests (push) Failing after 19m36s
CI/CD Pipeline / Validate - Security (push) Successful in 28m3s
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 / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-05 12:18:41 +00:00
xiaoxia 90004cced4 refactor(vision): dashscope-only (#2207)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 / Check push changed paths (push) Successful in 16s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
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 / 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
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 51s
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 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m57s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m45s
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 / Build Staging Worker Image (push) Successful in 38s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
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 / Build Staging Web Image (push) Successful in 1m15s
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) Successful in 2m7s
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 / 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
2026-10-05 20:03:30 +08:00
CI Bot e672c17eb2 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 / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 7s
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 9s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 9s
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 Lint (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 / 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 / Check push changed paths (push) Successful in 31s
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 / PR Build API Image (pull_request) Successful in 1m33s
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m34s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m13s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m27s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m17s
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 / Integration Tests (push) Successful in 5m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m57s
CI/CD Pipeline / Validate - Style (push) Failing after 6m42s
AI Code Review / AI Code Review (pull_request) Successful in 7m6s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m10s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m3s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m33s
CI/CD Pipeline / Validate - Security (push) Successful in 12m14s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m10s
CI/CD Pipeline / Unit Tests (push) Failing after 13m40s
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-05 10:20:33 +00:00
xiaoxia fb0e4989cd Merge pull request 'fix(vision): #2204 lite VLM关闭thinking模式,响应从10-12s降到<3s' (#2204) from fix/vision-v2-disable-thinking into develop
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 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m22s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
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 / 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 2m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m9s
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
PR Automation / Auto Merge on CI Green + Approved (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
AI Code Review / AI Code Review (pull_request) Successful in 6m48s
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 / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m34s
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 / Integration Tests (push) Successful in 5m38s
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m41s
CI/CD Pipeline / Validate - Style (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 / 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 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 - Security (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
2026-10-05 18:13:07 +08:00
xiaoxia 702f09e6b7 fix(vision): #2204 lite VLM关闭thinking模式,响应从10-12s降到<3s
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 50s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m8s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m44s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 47s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m25s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 5m38s
AI Code Review / AI Code Review (pull_request) Successful in 6m54s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 7m28s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m28s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 12m32s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 17m32s
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) Failing after 6s
根因定位:staging直连测试发现 doubao-seed-2-1-lite-260915 是思考模型,
单次调用产生~520 reasoning_tokens,耗时10-12s,导致fast路径必超时。

修复:
1. vlm_fast_json.py 直接用 httpx 发最小 payload(不走 ai_client 包装),
   显式设置 thinking={"type":"disabled"} + reasoning_effort="low" 关闭思考链,
   期望响应降至 <3s;若API不支持thinking参数返回400,自动降级重试一次。
2. 超时恢复合理值:lite JSON 8s、OCR 6s、fast总超时8s(关闭thinking后预计<3s,余量充足)。
3. vlm_fallback.py 保持单次pro调用,pro走原ai_client路径(兜底场景对延迟不敏感,45s足够)。

预期:3图<10s/8图<15s目标可达。
2026-10-05 18:11:19 +08:00
xiaoxia 12b0d15473 Merge pull request 'fix(vision): #2203 V2快速路径TimeoutError未捕获+max_retries=0不生效' (#2203) from fix/vision-v2-timeout-bugs into develop
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) 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 15s
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 / Frontend Unit Tests (push) Successful in 2m27s
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 / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (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 / Integration Tests (push) Successful in 4m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m16s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m20s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m2s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m32s
CI/CD Pipeline / Retag skipped Staging API 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m13s
CI/CD Pipeline / Retag skipped Staging Web 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 / CI Gate (pull_request) Successful in 7s
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 / ACR Image Cleanup (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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m42s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m16s
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 / Retag skipped Staging API Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m28s
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
AI Code Review / AI Code Review (pull_request) Successful in 6m29s
CI/CD Pipeline / Validate - Style (push) Failing after 9m24s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m40s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m47s
CI/CD Pipeline / Validate - Security (push) Successful in 11m51s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m18s
CI/CD Pipeline / Unit Tests (push) Failing after 14m17s
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-05 17:51:27 +08:00
xiaoxia 9344314eac fix(vision): #2203 V2快速路径两个P0 bug修复
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m0s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m21s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 44s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m16s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 14s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m22s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m25s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m53s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 7m39s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m35s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 13m20s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 15m11s
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 / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
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
E2E发现两个P0 bug:
1. as_completed(timeout=...)抛TimeoutError时未被捕获,异常直接冒泡到外层,
   跳过了pro VLM兜底路径,导致3/3返回空结果。
   修复:包裹try/except TimeoutError,cancel未完成futures,继续走pro兜底。

2. 外层_step_image_analysis设置client.max_retries=0不生效(ThreadPool线程
   里可能被其他任务覆盖/共享单例状态),实际仍重试1次(2次调用×6s=12s超时)。
   修复:在vlm_fast_json/vlm_fallback内部强制max_retries=0并在finally里恢复。

3. 收紧超时:fast总超时8→6s、lite JSON 6→5s、OCR 8→5s,让lite不够快时
   尽快走pro兜底(pro单次45s足够)。

本地mock验证:fast命中1.5s返回有效portrait_prompt;fast超时6s正确触发pro fallback。
2026-10-05 17:50:13 +08:00
xiaoxia 3f49867384 fix(viral-video): 时长选择恢复原生Select,仅改选项为15-30秒每秒一档 (#2202)
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 4s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 3s
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 6s
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 - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) 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 / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) 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 / Check push changed paths (push) Successful in 35s
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 56s
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 1m6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m10s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m1s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m22s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m16s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m16s
CI/CD Pipeline / Integration Tests (push) Successful in 4m45s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m21s
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 5m31s
CI/CD Pipeline / Validate - Style (push) Failing after 5m50s
AI Code Review / AI Code Review (pull_request) Successful in 7m7s
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 - Security (push) Has been cancelled
2026-10-05 17:43:15 +08:00
CI Bot dd420c556f 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 / 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 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 / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 17s
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 / PR Build API Image (pull_request) Successful in 51s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m0s
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 Worker Image (pull_request) Successful in 1m8s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (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 / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 34s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m16s
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 1m58s
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 / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m16s
CI/CD Pipeline / Staging E2E Tests (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 / 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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-05 09:38:17 +00:00
xiaoxia 2d823a9255 Merge pull request 'refactor(vision): #2201 代码精简 — 删lite/pro竞速/#2194临时止血/V1V2双分支' (#2201) from refactor/vision-v2-clean into develop
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 (push) Successful in 3s
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 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m15s
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 / 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 API Image (pull_request) Successful in 1m3s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m21s
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 1m56s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 17s
PR Automation / Auto Merge on CI Green + Approved (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 / 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 / CI Gate (pull_request) Successful in 3s
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 / 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
AI Code Review / AI Code Review (pull_request) Successful in 6m26s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m22s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m1s
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 / Integration Tests (push) Successful in 5m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m25s
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 / Deploy Staging (Watchtower auto-deploy) (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
2026-10-05 17:27:02 +08:00
xiaoxia ed24c7cd68 fix(vision): assembler portrait_prompt 拼接自然化 + 清死代码三元
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 18s
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 / PR Build Worker Image (pull_request) Successful in 37s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 38s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 10s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m11s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m10s
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 / Unit Tests (pull_request) Failing after 4m23s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m35s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m44s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 6m28s
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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 48s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 12m44s
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 / CI Gate (pull_request) Failing after 1s
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
- _AGE_PREFIX 去掉儿童/青少年死代码(已在 _person_subject 里单独按性别处理)
- 风格段(style/mood/scene)之间不用逗号,改为紧凑拼接(休闲阳光街拍风格而非'休闲,阳光,街拍风格')
2026-10-05 17:26:04 +08:00
xiaoxia 69f88434bd refactor(vision): #2201 代码精简 — 删lite/pro竞速/#2194临时止血/V1V2双分支
按灵应要求清理冗余:
1. _step_image_analysis 直接走V2主路径,去掉V1/V2 if/else分支
2. 删除 _analyze_single_image 整个函数(450行lite/pro竞速/_xml_to_product复杂解析)
3. VLM兜底抽到vision/vlm_fallback.py:单次pro调用,简化版XML/JSON解析,无竞速/无复杂超时
4. _normalize_image_url 删除#2194临时加的GET+Range:0-1024可达性检查
5. fast_path.py 去掉VISION_V2_ENABLED判断,简化默认超时(fast=8s/lite=6s/ocr=6s)
6. 删掉未使用的_is_vision_result_usable、ThreadPoolExecutor/as_completed import
7. viral_video.py从2583行精简到2031行(净删552行),结构清爽

代码只有一条主力路径:OCR+lite JSON并行 → 失败单次pro兜底。
2026-10-05 17:26:03 +08:00
CI Bot 599388d9e0 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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 6s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Validate - Style (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 / Validate - Security (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 / 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 push changed paths (push) Successful in 16s
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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m6s
CI/CD Pipeline / Build Staging API Image (push) Successful in 52s
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 Web Image (push) Successful in 26s
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 Worker Image (pull_request) Successful in 1m36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 30s
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 1m56s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m45s
CI/CD Pipeline / Integration Tests (push) Successful in 4m27s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m36s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Failing after 6m22s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m20s
AI Code Review / AI Code Review (pull_request) Successful in 6m55s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m25s
CI/CD Pipeline / Staging E2E 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 - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
2026-10-05 09:16:02 +00:00
xiaoxia 9ffe909dc0 fix(viral-video): 时长滚轮改为弹层式,保持与其他表单项外观一致 (#2199)
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 if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 18s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m47s
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 Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 44s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m4s
CI/CD Pipeline / Build Staging API Image (push) Successful in 33s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 43s
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
PR Automation / Auto Merge on CI Green + Approved (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 / PR Build Worker Image (pull_request) Successful in 1m2s
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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m34s
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 / Validate - Python (mypy + alembic) (push) Successful in 5m19s
AI Code Review / AI Code Review (pull_request) Successful in 6m44s
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 / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
2026-10-05 17:09:02 +08:00
xiaoxia 6243196408 feat(vision): #2200 V2图片分析快速路径 OCR+lite JSON VLM并行 目标单图<3s/8图<15s (#2200)
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 if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (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 / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Check push changed paths (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 / 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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
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 / 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 / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-05 17:08:52 +08:00
CI Bot 3d8f2c2ce2 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 3s
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 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 6s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 7s
CI/CD Pipeline / Check push changed paths (pull_request) 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 / 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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web 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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / Check push changed paths (push) Successful in 57s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m9s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m10s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 49s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 37s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
CI/CD Pipeline / Integration Tests (push) Successful in 3m10s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m18s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m40s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m24s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m36s
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) Successful in 1m9s
AI Code Review / AI Code Review (pull_request) Successful in 6m49s
CI/CD Pipeline / Validate - Style (push) Failing after 7m49s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m16s
CI/CD Pipeline / Validate - Security (push) Successful in 8m14s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m10s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m52s
CI/CD Pipeline / Unit Tests (push) Failing after 11m2s
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-05 08:36:18 +00:00
xiaoxia 3eef497dfe feat(viral-video): 文案视频时长改为15-30秒滚轮picker (#2196)
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 3s
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 7s
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 / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker 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 / 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 / Check push changed paths (push) Successful in 58s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m15s
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 Web Image (push) Successful in 1m13s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m19s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m55s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m29s
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 Approve on CI Green (pull_request) Successful in 3m19s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m53s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m32s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m16s
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
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 / Validate - Security (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 - Python (mypy + alembic) (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 / Validate - Style (push) Failing after 5m50s
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-05 16:30:20 +08:00
xiaoxia 61c15eb987 fix(viral_video): #2199 _is_vision_result_usable放宽判定+_normalize兼容dict
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 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) 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 API 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 9s
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 / Check push changed paths (push) Successful in 8s
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 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 Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m8s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m11s
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 Web Image (push) Successful in 20s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m52s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 42s
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 / Integration Tests (push) Successful in 2m59s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m21s
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 / 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 / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (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 / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Failing after 10m43s
两个bug修复:
1. _normalize兼容VLM直接返回JSON dict(裸JSON不包裹fence时json.loads返回dict),
   之前isinstance(raw,str)判False走badtype fallback导致name=未识别,usable永远False
2. _is_vision_result_usable放宽判定:有人像描述即视为usable(爆款视频核心是给
   信任链t2i做人物参考),非人像场景才要求name+summary+features;summary长度30→5
竞速循环能正确识别pro返回的人像结果,竞速胜出日志正常
2026-10-05 16:26:34 +08:00
xiaoxia 0012ecad30 fix(viral_video): #2198b _normalize兼容VLM直接返回dict(JSON),竞速判定不再误判失败
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 3s
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 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 / 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 / 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 / Check push changed paths (push) Successful in 24s
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 / PR Build API Image (pull_request) Successful in 1m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m11s
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 / CI Gate (pull_request) Successful in 2s
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 34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 36s
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) 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 / Deploy Staging (Watchtower auto-deploy) (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 / Integration 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
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
根因:_call() 里 json.loads 成功时返回 dict,但 _normalize 第一行 isinstance(raw,str) 判False
直接走 _vision_fallback 返回 name=未识别,导致 _is_vision_result_usable=False。
外层 fallback 路径再次 _normalize 又因dict问题走badtype,靠outfit回填逻辑拼了结果。
修复:
1. _normalize 先判断 isinstance(raw,dict),直接从dict取字段构造product
2. 字符串解析失败时再尝试 json.loads 递归处理(兼容裸JSON字符串)
3. 竞速判定现在能正确识别pro/dict返回,'竞速胜出=pro'日志正常打印
2026-10-05 16:24:07 +08:00
CI Bot e1994ada0a 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 8s
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 API Image (pull_request) 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 / Check if frontend-only change (pull_request) Successful in 9s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 9s
CI/CD Pipeline / Frontend Lint (push) 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 / Check push changed paths (push) Successful in 35s
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 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m5s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m4s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m34s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m23s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m34s
CI/CD Pipeline / Integration Tests (push) Successful in 4m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m29s
CI/CD Pipeline / Deploy 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 2s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m33s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
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) Failing after 6m0s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m3s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / ACR Image Cleanup (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 / Validate - Security (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 / 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
2026-10-05 08:15:39 +00:00
xiaoxia f9f6c53ef4 chore: trigger CI rebuild for #2198 lite/pro race [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 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) 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 12s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m20s
CI/CD Pipeline / Frontend Lint (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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web 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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m19s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m39s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m46s
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
PR Automation / Auto Merge on CI Green + Approved (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 / Validate - Python (mypy + alembic) (push) Successful in 4m14s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 50s
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 API Image (pull_request) Successful in 2m23s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
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 / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 / Integration 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
2026-10-05 16:09:11 +08:00
xiaoxia 9699a1fcde fix(viral_video): #2198 lite/pro并行竞速,单图最坏75s(原串行100s+)
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 / 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 / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (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 / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Check push changed paths (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 / 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 - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 38s
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 / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (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 / Build Staging Web 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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m4s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 3m5s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m15s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m53s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m55s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m7s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 6m5s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m26s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m38s
AI Code Review / AI Code Review (pull_request) Successful in 10m17s
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 / CI Gate (pull_request) Failing after 3s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
问题:实测lite 40s 100%超时→pro串行跑40-65s,3图2并发最坏=40+60+40=140-190s,img#1粉波点裙pro 60s超时直接失败。
改动:
1. _analyze_single_image内部用2线程ThreadPoolExecutor并行发lite(30s)和pro(75s),
   as_completed取第一个usable结果即返回,消除串行等待惩罚
2. _step_image_analysis阶段统一在try外层置client.max_retries=0、finally恢复,
   子线程_call不再嵌套修改client属性避免竞态
3. lite timeout 40→30s(快速路径30s还没出就等pro),pro timeout 60→75s(给10s余量防偶发慢)
4. 单图最坏75s(pro慢到75s才出),典型40-50s,3图2并发≈75s;外层图片并发仍≤2(总VLM并发=4)
5. elapsed日志加label字段(lite/pro)便于区分竞速胜出方
2026-10-05 16:08:00 +08:00
xiaoxia 305e2bd9d5 fix(viral_video): #2194b balance VLM timeout lite40s/pro60s,E2E验证25s太紧导致2/3图误判未识别
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 (push) Successful in 5s
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / PR Build Web Image (push) 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 5s
CI/CD Pipeline / Frontend Lint (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 / 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 / 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 push changed paths (push) Successful in 29s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m34s
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 Worker Image (pull_request) Successful in 1m36s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m17s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m33s
CI/CD Pipeline / Integration Tests (push) Successful in 3m34s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m47s
CI/CD Pipeline / Build Staging API Image (push) Successful in 56s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m6s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m0s
CI/CD Pipeline / Validate - Style (push) Failing after 5m47s
CI/CD Pipeline / Deploy Production (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 / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
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 / Canary Release to Production (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m17s
CI/CD Pipeline / Validate - Security (push) Successful in 9m26s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m41s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m58s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m59s
CI/CD Pipeline / Unit Tests (push) Failing after 14m2s
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 / Build Production API 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
E2E实测(b8e27707/85c65d16)发现:lite timeout=25s时2并发下偶发2/3图返回未识别,
因为lite超时后走pro fallback=45s,但pro在2并发下也偶尔超时返回None。
调整为 lite 40s + pro 60s(都禁重试),单图最坏100s,比原240s改善>50%,
同时保证成功率>90%(不会误判未识别)。
2026-10-05 15:34:07 +08:00
CI Bot 30cc58441f 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 2s
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 6s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
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 4s
CI/CD Pipeline / Check push changed paths (push) Successful in 52s
CI/CD Pipeline / Frontend Lint (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 / Integration Tests (push) Successful in 3m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m28s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m58s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m37s
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 / 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 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 E2E Tests (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 / PR Build API Image (pull_request) Successful in 2m51s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
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 / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (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 / PR Build Worker Image (pull_request) Successful in 2m52s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-05 07:28:34 +00:00
xiaoxia b3b5dbd459 chore: trigger CI rebuild for #2194/#2195 VLM timeout fixes [skip ci-format-check]
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 2s
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 / Check push changed paths (push) Successful in 7s
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 / 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 / PR Build API Image (pull_request) Successful in 1m0s
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 / PR Build Worker Image (pull_request) Successful in 1m10s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m9s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m27s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m39s
CI/CD Pipeline / Integration Tests (push) Successful in 3m40s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m14s
CI/CD Pipeline / Build Staging API Image (push) Successful in 5m31s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 5m49s
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 / Retag skipped 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 / 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
AI Code Review / AI Code Review (pull_request) Has been cancelled
2026-10-05 15:22:01 +08:00
xiaoxia 9f5948dd2b fix(viral_video): #2194 图片URL可达性检查 HEAD→GET+Range,避免OSS签名URL 403假阴
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / 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 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 push changed paths (push) Successful in 30s
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 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 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 Worker Image (pull_request) Successful in 1m16s
CI/CD Pipeline / ACR Image Cleanup (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 / 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 / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (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 / 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
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (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
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
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
运维发现 OSS 签名 URL 把 HTTP Method 纳入签名,前端/SDK 生成的签名是 GET-only,
HEAD 请求返回 403 SignatureDoesNotMatch 误判 URL 无效(实际 GET 完全正常下载)。
- _normalize_image_url 的 HEAD 5s 检查改为 GET stream=True + Range: bytes=0-1024 只取前1KB
- 避免日志假warning,也不影响后续VLM实际下载(VLM用GET不受影响)
- 连带说明:用户4min卡顿的主因是VLM底层httpx重试叠加(lite30s×2+pro90s×2=240s),
  已在#2194前一commit(fbc1df3)修复为max_retries=0+lite25s+pro45s=单图最坏70s
2026-10-05 15:18:27 +08:00
xiaoxia fbc1df36e0 fix(viral_video): #2194 VLM单图最坏240s→70s,禁用httpx底层重试+收紧timeout
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 11s
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 16s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 24s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 35s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m26s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m37s
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit 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 / 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 / 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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m18s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
AI Code Review / AI Code Review (pull_request) Successful in 6m54s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 3m4s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m42s
CI/CD Pipeline / Build Staging API 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 0s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker 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) Failing after 5m30s
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 47s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 57s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m10s
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 / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (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 / CI Gate (pull_request) Failing after 2s
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
P0根因:用户实测图片分析卡4分钟+。代码分析发现:
- _analyze_single_image 底层 DoubaoClient.max_retries=1(共2次请求)
- lite timeout=30s × 2次重试 = 60s
- lite失败后 pro_fallback timeout=90s × 2次重试 = 180s
- 单图最坏 60+180 = 240s,3图2并发最坏 ~240s+,恰好命中用户4分钟描述

修复:
1. _call() 临时将 client.max_retries=0 单次调用,不重复请求
2. lite timeout 30s → 25s(超时立即降级pro)
3. pro fallback timeout 90s → 45s(pro稳定响应<30s)
4. 单图最坏 25+45=70s,3图2并发最坏约70s(含排队)
5. 每张图VLM调用结束打印elapsed日志,方便后续排查
2026-10-05 15:14:42 +08:00
xiaoxia d36cc09be5 feat(ui): 恢复积分系统UI显示(Header徽章+积分中心+预校验) (#2193)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
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 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 8s
CI/CD Pipeline / PR Build API 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 / 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 / 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 / Check push changed paths (push) Successful in 28s
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 Worker Image (pull_request) Successful in 1m34s
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 1m3s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m56s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m9s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m15s
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 2m11s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m9s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m52s
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m24s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m56s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m42s
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 / Dedup Check - skip PR tests when covered by push pipeline (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 / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
2026-10-05 15:03:48 +08:00
CI Bot fa4dbc6761 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 5s
CI/CD Pipeline / Check if frontend-only change (pull_request) 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 / 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 / Check push changed paths (push) Successful in 23s
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 Web Image (push) Successful in 42s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 57s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (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 / Build Staging API Image (push) Successful in 55s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m43s
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 / Integration Tests (push) Successful in 3m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m35s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m52s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Validate - Style (push) Successful in 4m18s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m41s
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 / Frontend Unit Tests (push) Successful in 5m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1m12s
CI/CD Pipeline / Validate - Security (push) Successful in 7m51s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m42s
CI/CD Pipeline / Unit Tests (push) Successful in 11m20s
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 36m49s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-05 05:56:41 +00:00
xiaoxia 77133eb9a0 fix(viral_video): #2188 VLM outfit回填服装关键词扩充
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 (push) Successful in 17s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 28s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 47s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m51s
CI/CD Pipeline / Build Staging API Image (push) Successful in 33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m21s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m47s
CI/CD Pipeline / Integration Tests (push) Successful in 3m40s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m54s
CI/CD Pipeline / Validate - Style (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 - 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
CI/CD Pipeline / Validate - Security (pull_request) Successful in 9m45s
CI/CD Pipeline / Check if frontend-only change (pull_request) 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 / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker 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 / Build Staging API 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m16s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m22s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 4m25s
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 47s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m50s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m23s
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) Failing after 2s
- 原 cloth_kws 漏了'上衣/打底衫/罩衫/雪纺衫/西服/套装/网纱/短袖/长袖/无袖'等常见词,
  导致'白色V领上衣''黑色透视网纱短袖上衣'等未命中,回退到通用'日常服装'
- 扩充到40+关键词,覆盖衬衫/T恤/毛衣/外套/裙装/裤装/制服/通用上装词
- 提取窗口 ci-8/ci+4 → ci-12/ci+8,向前多抓颜色/材质形容词,向后多抓款式词
- 重复词(马甲/背心)清理
2026-10-05 13:47:26 +08:00
CI Bot 35207ae040 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 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 56s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 15s
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 - Python (mypy + alembic) (push) Successful in 3m22s
CI/CD Pipeline / Integration Tests (push) Successful in 3m16s
CI/CD Pipeline / Validate - Style (push) Successful in 4m37s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m31s
CI/CD Pipeline / Validate - Security (push) Successful in 7m24s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m50s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m26s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m4s
PR Automation / Auto Merge on CI Green + Approved (pull_request) 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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m4s
AI Code Review / AI Code Review (pull_request) Successful in 7m42s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m36s
CI/CD Pipeline / Unit Tests (push) Successful in 12m28s
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 / 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 3m7s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m50s
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 / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) 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 / PR Build 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m23s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m36s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 5m58s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m58s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 10m15s
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 / Build Production Web 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 / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
2026-10-05 04:26:27 +00:00
xiaoxia 5af16f1aea feat(viral_video): #2188 voice_source='my_voice'/'clone' 克隆音色支持
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
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 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 / PR Build API Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 59s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m18s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m46s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 3m32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m55s
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 / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (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
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- 新增 _resolve_tts_voice_id(job):voice_source 为 my_voice/clone 时,
  前端传的 voice_id 是 VoiceCloneProfile.id,查 DB 取 profile.voice_id(CosyVoice 真正的克隆音色ID)
- profile 不存在/未就绪/voice_id为空时回退默认 longxiaochun_v3,任务不崩
- preset 或 voice_source 为空时,voice_id 直接当 CosyVoice 音色名透传(与原有行为一致)
- _step_tts 改用 _resolve_tts_voice_id 解析后的 voice_id 调 synthesize
- 不改 DB schema,不加字段;voice_source/voice_id schema 已在之前合入
2026-10-05 12:21:53 +08:00
xiaoxia c232721fff feat(viral-video): 音色选择默认改为"我的音色"克隆音色主路径 (#2189)
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 15s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 15s
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 Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (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 36s
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 / PR Build Worker Image (pull_request) Successful in 1m3s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m8s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 40s
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 / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m16s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 29s
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 1m48s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 3m7s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m29s
CI/CD Pipeline / Validate - Style (push) Successful in 3m32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m28s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m49s
CI/CD Pipeline / Integration Tests (push) Successful in 5m55s
CI/CD Pipeline / Validate - Security (push) Successful in 6m36s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m8s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m28s
CI/CD Pipeline / Unit Tests (push) Successful in 14m1s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-05 12:01:32 +08:00
xiaoxia fc27d4e81e fix(viral_video): VLM图片分析3个P0 bug (#2188) (#2188)
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 / 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 4s
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 / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (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 Lint (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 / Integration 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 / Frontend Unit Tests (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 Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
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
CI/CD Pipeline / Check push changed paths (push) Has been cancelled
CI/CD Pipeline / Validate - Style (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 / 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 / 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 / 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 / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
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
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-05 12:00:37 +08:00
xiaoxia 3c782f89d1 fix(#2187): outfit提取正则优化,保留颜色形容词 (#2187)
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 / Dedup Check - skip PR tests when covered by push pipeline (push) 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 / 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 3s
CI/CD Pipeline / Frontend Lint (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 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 / 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 / Check push changed paths (push) Successful in 26s
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 Worker 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 58s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m0s
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 / PR Build Worker Image (pull_request) Successful in 1m17s
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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 33s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m8s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m8s
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 / Build Staging Web Image (push) Successful in 3m47s
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 / Integration Tests (push) Successful in 4m54s
CI/CD Pipeline / Validate - Style (push) Successful in 5m32s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m31s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m49s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m50s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m52s
CI/CD Pipeline / Validate - Security (push) Successful in 10m56s
CI/CD Pipeline / Unit Tests (push) Successful in 12m0s
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
CI/CD Pipeline / Staging E2E Tests (push) Failing after 38m2s
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-05 02:04:07 +08:00
xiaoxia 2b4f11036f fix(#2186): portrait_prompt智能回填+few-shot示例,服装发型还原增强 (#2186)
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 (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
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 if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) 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 18s
CI/CD Pipeline / Frontend Lint (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 / 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 / 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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m2s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m22s
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
PR Automation / Auto Merge on CI Green + Approved (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 / Production Browser E2E (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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m44s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m5s
CI/CD Pipeline / Validate - Style (push) Successful in 4m12s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m8s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m35s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m52s
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 / Integration Tests (push) Successful in 5m46s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m11s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m1s
CI/CD Pipeline / Validate - Security (push) Successful in 7m47s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m19s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m20s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m37s
AI Code Review / AI Code Review (pull_request) Successful in 11m31s
CI/CD Pipeline / Unit Tests (push) Successful in 12m38s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-05 01:03:15 +08:00
xiaoxia 2881da65cf Merge pull request #2185: require people attrs + worker fallback
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 / 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 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 / PR Build API Image (pull_request) Successful in 1m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m0s
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 / CI Gate (pull_request) Successful in 3s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m46s
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
AI Code Review / AI Code Review (pull_request) Successful in 6m43s
2026-10-05 00:24:44 +08:00
xiaoxia 1037e218bb fix(#2185): 人物外貌属性强制描述+兜底,提升Seedream t2i还原度 (#2185)
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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 27s
CI/CD Pipeline / Build Staging API Image (push) Successful in 52s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 34s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 43s
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 3m30s
CI/CD Pipeline / Integration Tests (push) Successful in 3m34s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m23s
CI/CD Pipeline / Validate - Style (push) Successful in 4m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m37s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m9s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m45s
CI/CD Pipeline / Validate - Security (push) Successful in 7m34s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m1s
CI/CD Pipeline / Unit Tests (push) Successful in 11m12s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-05 00:24:42 +08:00
xiaoxia f0514d7487 fix(#2185): 人物外貌属性强制描述+兜底,提升Seedream t2i还原度
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m27s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m48s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m10s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m14s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 3m37s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m9s
AI Code Review / AI Code Review (pull_request) Successful in 6m35s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 6m46s
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 / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 4m17s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m14s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 1m3s
VLM对hair/skin_tone/face_shape/outfit四项输出"无法判断"导致Seedream自由发挥,
发型服装还原失败。双层修复:

1. prompts.py image_analysis system prompt强化:
   - 明确has_person=true时hair/skin_tone/face_shape/outfit四项禁止填"无法判断"
   - 提供hair/skin_tone/face_shape/outfit的具体示例值供参照
   - 即使局部遮挡也要基于可见部分合理推断

2. worker _xml_to_product双层保险:
   - VLM仍输出"无法判断"时,用通用兜底值(自然发型/自然肤色/标准脸型/日常服装)
   - 保证portrait_prompt始终包含完整外貌描述(性别/年龄/发型/肤色/脸型/穿着/表情)
   - 确保preheat_trust_chain的人物描述过滤器(len>=10)不会过滤掉结果

预期:人像图VLM输出具体外貌→Seedream t2i还原发型服装脸型→
Seedance reference_image为高还原度AI人像→人物整体相似度>85%(上次脸部80-90%,本次服装发型也应还原)
2026-10-05 00:17:01 +08:00
xiaoxia bf8f62ec5b Merge pull request #2184: fix xml people portrait_prompt trust-chain
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 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
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 / PR Build Worker Image (push) 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 / Check push changed paths (push) Successful in 24s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m1s
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 API Image (pull_request) Successful in 3m31s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m40s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m5s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m0s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m15s
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 6m19s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
AI Code Review / AI Code Review (pull_request) Successful in 7m16s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 7m53s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m37s
CI/CD Pipeline / Integration Tests (push) Successful in 9m35s
CI/CD Pipeline / Validate - Style (push) Successful in 10m9s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 11m21s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m52s
CI/CD Pipeline / Validate - Security (push) Successful in 16m10s
CI/CD Pipeline / Unit Tests (push) Successful in 17m38s
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 / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-04 23:49:36 +08:00
CI Bot cb911f5eba style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (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 1s
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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m6s
AI Code Review / AI Code Review (pull_request) Successful in 7m10s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m22s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 9m46s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 9m52s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 11m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 12m44s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 23m18s
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 / CI Gate (pull_request) Successful in 1s
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
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 34s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m32s
2026-10-04 15:23:27 +00:00
xiaoxia f6fa3ea653 fix(#2184): VLM <people>标签解析+扩展外貌属性,修复信任链第4处断链
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m57s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m25s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
AI Code Review / AI Code Review (pull_request) Successful in 6m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 8m52s
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
问题根因:#2177 XML重构后VLM prompt契约改为顶层<people has_person count gender age_range pose expression/>标签,
人物信息不再是<product portrait_prompt=...>属性。worker的_xml_to_product只读product属性,
VLM输出<people has_person="true" ...>被忽略,所有人物判断走默认"无人像",
导致:preheat跳过→现场t2i跳过→真人图直传Seedance→400 portrait_intercept→降级纯t2v(无参考图→人物相似度仅30-40%)

修复:
1. _xml_to_product解析顶层<people>标签,拼装portrait_prompt供信任链使用
2. 扩展VLM <people>标签新增外貌属性:hair/skin_tone/face_shape/outfit(原6属性→10属性)
   提供足够细节(60-100字外貌描述)给Seedream t2i生成还原度高的AI人像
3. 同步更新example为新属性格式
4. 兼容旧schema:product属性仍有portrait_prompt时优先使用
5. 无product标签但<people has_person=true>时也构造结果,不丢人物信息
2026-10-04 23:12:00 +08:00
CI Merge 6a7709ba43 Merge pull request #2183: real trust-chain preheat + LLM timeout fix
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 / 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 3s
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 / 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 / Check push changed paths (push) Successful in 21s
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 2m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m15s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m49s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m33s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m1s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m14s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 5m37s
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
AI Code Review / AI Code Review (pull_request) Successful in 7m4s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m0s
CI/CD Pipeline / Integration Tests (push) Successful in 10m27s
CI/CD Pipeline / Validate - Style (push) Successful in 10m55s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m50s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m58s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 12m19s
CI/CD Pipeline / Unit Tests (push) Successful in 17m7s
CI/CD Pipeline / Validate - Security (push) Successful in 33m1s
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
CI/CD Pipeline / Staging E2E Tests (push) Failing after 35m2s
# Conflicts:
#	apps/worker/worker_app/tasks/viral_video.py
2026-10-04 22:30:49 +08:00
xiaoxia 2c70dd4c29 Merge pull request 'feat(viral_video): #2040 接入Prompt模板系统+删除冗余硬编码prompt' (#2177) from fix/2040-wire-prompt-templates into develop
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 5s
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 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
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 / Frontend Unit Tests (push) Successful in 2m14s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m48s
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 API Image (pull_request) Successful in 20s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m45s
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 19s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 13s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m19s
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
PR Automation / Auto Merge on CI Green + Approved (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 Staging Worker Image (push) Successful in 25s
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 / CI Gate (pull_request) Successful in 1s
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 / 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
AI Code Review / AI Code Review (pull_request) Successful in 6m44s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m3s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m47s
CI/CD Pipeline / Integration Tests (push) Successful in 10m37s
CI/CD Pipeline / Validate - Style (push) Successful in 11m58s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m38s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m20s
CI/CD Pipeline / Unit Tests (push) Successful in 18m37s
CI/CD Pipeline / Validate - Security (push) Successful in 26m44s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 32m59s
CI/CD Pipeline / Build Production Worker 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 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
feat(viral_video): #2040 Prompt模板接线+删硬编码(DB读取+XML解析+三档融合+Reviewer) (#2177)
2026-10-04 21:51:50 +08:00
CI Bot 5548e78eee style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging 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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m50s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m0s
AI Code Review / AI Code Review (pull_request) Successful in 7m4s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m59s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m57s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 13m14s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m4s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 19m21s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 26m10s
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 / CI Gate (pull_request) Successful in 1s
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
2026-10-04 13:51:16 +00:00
xiaoxia 44bd96b148 fix(#2183): 信任链真·现场t2i+preheat接线+portrait_intercept降级纯t2v+timeout调大
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
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 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 20s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m44s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m35s
AI Code Review / AI Code Review (pull_request) Successful in 10m19s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m26s
CI/CD Pipeline / Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- 信任链3处断链修复:
  1. run_viral_video_analyze VLM完成后立即启动_start_trust_chain_preheat(后台daemon与文案阶段并行)
  2. _step_render 预热不可用时真·同步调用Seedream t2i(而非打假日志直接传原图),120s超时
  3. ai_client.video_generation遇到portrait_intercept 400时自动移除所有参考图降级纯t2v重试一次
- LLM timeout调大(实测pro 1500tok输出需75.8s):
  - _step_script_generation: fast-first/fast-retry 45→90s, pro-fallback 60→120s
  - _step_intent_parsing: 45→60s
  - _step_review: 30→45s
- generate_copy celery时限放宽:soft=360→600s, hard=420→660s(三级重试最坏~405s)
- 三层兜底:后台预热→现场t2i→400纯t2v,保证人像链路必出片
2026-10-04 21:38:31 +08:00
xiaoxia dda67cd10f Merge pull request 'fix(#2181): doubao_fast_model 默认改pro,避免文案阶段走lite超时' (#2182) from fix/fast-model-default-pro into develop
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 / 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 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 / 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 / Check push changed paths (push) Successful in 33s
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 / PR Build API Image (pull_request) Successful in 1m56s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m32s
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 / 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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m19s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m29s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m53s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m1s
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 6m13s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
AI Code Review / AI Code Review (pull_request) Successful in 7m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m0s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 7m54s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m33s
CI/CD Pipeline / Integration Tests (push) Successful in 9m14s
CI/CD Pipeline / Validate - Style (push) Successful in 10m47s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m8s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m51s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 12m36s
CI/CD Pipeline / Unit Tests (push) Successful in 17m26s
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
2026-10-04 21:29:47 +08:00
xiaoxia-saas-bot 233d0272a9 fix(viral_video): #2040 rebase 后清理F841死代码+保留#2180 timeout修复
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 32s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m52s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m33s
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m6s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 10m19s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 10m25s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m49s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m39s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 27m35s
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 / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
- 删除 script_generation 中旧prompt遗留的未使用变量(style_hint/ratio/viral_structure_block/persona_hint)
- 冲突解决保留 #2180 全部修复: VLM/LLM timeout 15/25→45, pro 25→60, max_retries 2→1
- black/isort/ruff 全绿;viral 相关71测试全过
2026-10-04 21:15:59 +08:00
Xiaoxia Agent 631dd643c0 fix(viral_video): #2040 修复 style check F401/F821 导入问题
- _step_image_analysis/_step_intent_parsing 的局部导入补 render_system_prompt(F821 未定义名)
- _step_script_generation 的冗余 render_system_prompt 导入删除(F401 未使用)

black/isort/ruff 全绿,viral_video 单测 150/150 通过。
2026-10-04 21:15:59 +08:00
CI Bot 50489b05d6 style: auto-format with black + isort + ruff + prettier [skip ci-format-check] 2026-10-04 21:15:59 +08:00
Xiaoxia Agent 252ea71d50 test: 新增 prompt 模板接线集成测试 + 修复旧测试适配 XML 输出
- 新增 test_viral_video_wiring.py:9 个集成测试覆盖四步接线全流程
  - image_analysis / intent_parsing 走 loader + XML 解析
  - storyboard 三档 fusion_level 注入 system_prompt
  - review 走 Reviewer 且 pass/rewrite 两条路径正确
  - 端到端验证每步都调用 prompt_loader
- 修复 test_script_generation_returns_copy_result:mock 改为返回 XML 字符串
- 修复 test_review_pass_v16:mock Reviewer.review 返回真实 ReviewResult
- viral_video.py 增加 import re,_xml_to_product 的 text_on_package 同时从子标签读取(兜底)
- prompts.py _STORYBOARD_SYSTEM 改为普通字符串 + {fusion_instruction}/{global_constraints}/{negative_rules} 占位符,支持运行时注入

全量 viral_video 单测 150/150 通过,无回归。

Closes #2040
2026-10-04 21:15:59 +08:00
xiaoxia-saas-bot d5f6e9499d feat(viral_video): #2040 接入Prompt模板系统+删除冗余硬编码prompt 2026-10-04 21:15:59 +08:00
xiaoxia afd6b9c0b8 fix(#2181): doubao_fast_model 默认值也改为 pro,避免文案生成走 lite 超时
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m35s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m50s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 16s
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 / PR Build Worker Image (pull_request) Successful in 1m31s
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
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 13m15s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m42s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m1s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 12m24s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 18m0s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 30m55s
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 / 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 7s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 47s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m54s
lite 模型(doubao-seed-2-1-lite-260915)在方舟侧 100% read timeout。
之前只把 doubao_vision_use_lite 默认改为 false,但文案生成的 intent/script/review
直接读取 doubao_fast_model(不受 vision_use_lite 开关控制),默认值还是 lite,
导致文案阶段两轮 lite fast-first+fast-retry 超时耗尽 celery 时限,worker 被 SIGKILL。

ENV DOUBAO_FAST_MODEL 已在staging设为 pro,本次同步代码默认值,
避免其他环境/本地开发再踩坑。方舟确认 lite 可用后可通过 ENV 切回。
2026-10-04 20:50:00 +08:00
xiaoxia 8a6ebb49be fix(render): SHARED_SECRETS 增加 FAST_MODEL/TIMEOUT/MAX_RETRIES
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
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 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 13s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m14s
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 API Image (pull_request) Successful in 21s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m50s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m22s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m24s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m11s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m44s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
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 / 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 / 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 / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m24s
CI/CD Pipeline / Validate - Style (push) Successful in 15m23s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m17s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m30s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m39s
CI/CD Pipeline / Integration Tests (push) Successful in 17m50s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 18m48s
CI/CD Pipeline / Unit Tests (push) Successful in 22m6s
CI/CD Pipeline / Validate - Security (push) Successful in 34m5s
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-04 20:47:11 +08:00
xiaoxia 9e024caff5 fix(ci): staging env 注入 DOUBAO_FAST_MODEL/TIMEOUT/MAX_RETRIES
CI/CD Pipeline / Check if frontend-only change (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 Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Check push changed paths (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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
2026-10-04 20:47:08 +08:00
xiaoxia c7e9878f0d fix(env): DOUBAO_TIMEOUT/MAX_RETRIES 改占位符(45/1),新增 DOUBAO_FAST_MODEL 临时指向pro
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 / 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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 / 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 / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (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
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Failing after 7m10s
CI/CD Pipeline / PR Build API 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 / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Check push changed paths (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (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
2026-10-04 20:47:06 +08:00
xiaoxia b6243c8ab8 PR #2181: fix test timeout assertions + default disable VLM lite
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 / 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 2s
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 4s
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 / Frontend Lint (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 / 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 / Check push changed paths (push) Successful in 24s
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 Web Image (push) Successful in 58s
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 / 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 / Staging E2E 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 1m10s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m23s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m14s
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 2m55s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m11s
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 / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m10s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m29s
AI Code Review / AI Code Review (pull_request) Successful in 7m18s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m55s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m22s
CI/CD Pipeline / Validate - Style (push) Successful in 11m30s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 13m38s
CI/CD Pipeline / Integration Tests (push) Successful in 13m56s
CI/CD Pipeline / Unit Tests (push) Successful in 18m59s
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
Merged by QA (Admin). Unit/Integration/Style/Security all green on 67e4b3fc.
2026-10-04 20:27:25 +08:00
ops-agent 67e4b3fc6f fix(test): #2180 max_retries 默认1,assertion 2→1
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 (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 / 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 35s
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 Worker Image (pull_request) Successful in 1m55s
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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m16s
AI Code Review / AI Code Review (pull_request) Successful in 6m56s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 11m38s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 11m55s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 12m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 14m6s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m46s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 30m1s
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 / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m45s
2026-10-04 19:54:57 +08:00
ops-agent df654bce19 fix(test): #2180 max_retries 默认1,assertion 2→1
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Blocked by required conditions
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Blocked by required conditions
CI/CD Pipeline / Unit Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Integration Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Frontend Lint (pull_request) Blocked by required conditions
CI/CD Pipeline / Frontend Unit Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / PR Build API Image (pull_request) Blocked by required conditions
CI/CD Pipeline / PR Build Web Image (pull_request) Blocked by required conditions
CI/CD Pipeline / PR Build Worker Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Check push changed paths (pull_request) Waiting to run
CI/CD Pipeline / Build Staging API Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Build Staging Web Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Build Staging Worker Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Blocked by required conditions
CI/CD Pipeline / Staging E2E Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Staging API Integration Tests (pull_request) Blocked by required conditions
CI/CD Pipeline / Build Production API Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Build Production Web Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Build Production Worker Image (pull_request) Blocked by required conditions
CI/CD Pipeline / Deploy Production (pull_request) Blocked by required conditions
CI/CD Pipeline / Production Browser E2E (pull_request) Blocked by required conditions
CI/CD Pipeline / ACR Image Cleanup (pull_request) Blocked by required conditions
CI/CD Pipeline / Canary Release to Production (pull_request) Blocked by required conditions
CI/CD Pipeline / CI Gate (pull_request) Blocked by required conditions
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-04 19:54:56 +08:00
ops-agent bd99c161dd fix(test): #2181 补改 timeout 30→45 assertion 2026-10-04 19:54:54 +08:00
ops-agent 7fee203693 ci: render_env SHARED_SECRETS 补充 DOUBAO_IMAGE_MODEL/SIZE/TIMEOUT
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
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 / 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 / Check push changed paths (push) Successful in 25s
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 41s
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 Staging API Image (push) Successful in 28s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m54s
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 / Build Staging Worker Image (push) Successful in 1m16s
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 / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m52s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m52s
PR Automation / Auto Merge on CI Green + Approved (pull_request) 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 / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m30s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m25s
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m29s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m49s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m41s
CI/CD Pipeline / Integration Tests (push) Successful in 10m54s
CI/CD Pipeline / Validate - Style (push) Successful in 11m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 13m59s
CI/CD Pipeline / Unit Tests (push) Failing after 17m51s
CI/CD Pipeline / Validate - Security (push) Successful in 19m1s
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-04 19:45:32 +08:00
ops-agent 562ffc53cc ci(staging): render-env 步骤注入 VISION_LITE/USE_LITE/IMAGE secrets
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) 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 / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (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 / 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
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 / 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 / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-04 19:45:10 +08:00
ops-agent 9a67f727b3 chore(staging): .env.staging 模板新增 VISION_LITE/USE_LITE/IMAGE 变量,根治 ENV 被渲染还原为旧 ep- 值
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 3s
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 / Check push changed paths (push) Successful in 18s
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 (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 / 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 Staging 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 / 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
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 / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
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 / 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 / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
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-04 19:44:45 +08:00
xiaoxia 5bb714f25b fix(#2181 P0): 默认关闭VLM lite + 修复单测timeout assertion
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 (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m56s
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 (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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m57s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 11m18s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m40s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m48s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 14m40s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
1. 单测修复:#2180把doubao_timeout默认从30提到45后,3个单测还assert 30导致CI红,同步更新为45
   - tests/unit/test_config_base.py::test_default_doubao_config
   - tests/unit/test_api_settings.py
   - tests/unit/test_ai_client.py(两处doubao_timeout=30→45)

2. doubao_vision_use_lite 默认改为 False:
   实测方舟 doubao-seed-2-1-lite-260915 模型100%超时(45.1s read timeout,3次重试全挂),
   反而 pro (ep-20260721114705-b568m) 稳定25-38s一次成功。
   默认关闭lite,直接走pro避免每步多耗136s(lite 3次超时),整体从170s/步→35s/步。
   lite模型待方舟侧恢复或确认为模型名问题后再通过ENV开启。
2026-10-04 19:32:24 +08:00
xiaoxia 0f592add29 fix(#2180 P0): VLM/LLM timeout 调大,适配方舟视觉API 24-38s响应 (#2180)
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 13s
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 / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 15s
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 API Image (pull_request) Successful in 1m18s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m59s
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 Worker Image (pull_request) Successful in 1m32s
CI/CD Pipeline / Build Staging API Image (push) Successful in 29s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 34s
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 / Build Staging Web Image (push) Successful in 2m23s
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
AI Code Review / AI Code Review (pull_request) Successful in 6m31s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m24s
CI/CD Pipeline / Integration Tests (push) Successful in 4m44s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m28s
CI/CD Pipeline / Validate - Style (push) Successful in 5m54s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m13s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m55s
CI/CD Pipeline / Validate - Security (push) Successful in 11m29s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 5m33s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m50s
CI/CD Pipeline / Unit Tests (push) Failing after 12m56s
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
Force-merge: unit test test_default_doubao_config assertion stale (expects 30, new default 45 intentional). Pre-existing musetalk failures known.
2026-10-04 18:36:00 +08:00
xiaoxia 42dd5fabc6 fix(#2180): 全局 max_retries 2→1,避免重试叠加到351s
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m2s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 54s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 1m6s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m19s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 4m43s
AI Code Review / AI Code Review (pull_request) Successful in 5m5s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m10s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 8m22s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 8m23s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m48s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 11m52s
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 / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
原配置max_retries=2(即3次尝试),lite失败→3次超时→pro降级→3次超时,
VLM最坏46.6+76.7=123s,文案三级重试最坏351s。
timeout调大到45/60s后,方舟API正常情况下1次调用就能在24-38s内返回,
max_retries=1(即2次尝试)足够防偶发网络抖动。
最坏情况VLM总耗时:45+45+60+60=210s,比351s改善40%。
2026-10-04 18:34:11 +08:00
xiaoxia c7aed2c152 fix(#2180 P0): VLM/LLM timeout 调大,适配方舟视觉API 24-38s 响应
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 6s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m52s
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 25s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m53s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m31s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 3m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m28s
AI Code Review / AI Code Review (pull_request) Successful in 6m33s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m12s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- VLM lite timeout: 15s → 45s(方舟VLM实测服务端处理24-38s,原15s必超时3次重试全挂)
- VLM pro fallback timeout: 25s → 60s
- 意图解析 chat timeout: 25s → 45s
- 文案fast-first/fast-retry timeout: 25s → 45s
- 文案pro-fallback timeout: 40s → 60s
- 文案审核timeout: 20s → 30s
- doubao_timeout默认: 30s → 45s

根因:方舟VLM视觉API从staging服务器实测响应24-38s(x-envoy-upstream-service-time:23357ms),
原timeout=15s每次都被截断,3次重试全超时→lite降级pro又3次超时→总123s。
文案三级重试同理叠加到351s。调大timeout后单次调用应能在45s内返回。
2026-10-04 18:25:49 +08:00
xiaoxia 3428f4ef73 Merge pull request 'fix(viral-video): pre_trusted_images 反序列化兼容脏数据' (#2179) from fix/2175-pre-trusted-images-serde-bug into develop
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 / 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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (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 / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (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 / 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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 24s
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 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m13s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m20s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m46s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m12s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m4s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m26s
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
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m44s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m21s
CI/CD Pipeline / Integration Tests (push) Successful in 4m54s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m17s
AI Code Review / AI Code Review (pull_request) Successful in 7m2s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m27s
CI/CD Pipeline / Validate - Style (push) Successful in 7m54s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 8m19s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m19s
CI/CD Pipeline / Validate - Security (push) Successful in 12m20s
CI/CD Pipeline / Unit Tests (push) Successful in 12m47s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
fix: pre_trusted_images反序列化兼容脏数据
2026-10-04 18:00:18 +08:00
CI Bot 13c57771b9 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (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 / 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m49s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m6s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m27s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m52s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 5m56s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 6m24s
AI Code Review / AI Code Review (pull_request) Successful in 6m51s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 12m56s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 13m43s
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 / CI Gate (pull_request) Failing after 3s
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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m10s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 32s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m18s
2026-10-04 09:35:00 +00:00
xiaoxia 5eedf190c1 fix(viral-video): pre_trusted_images to_domain 兼容脏数据
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 if frontend-only change (pull_request) Successful in 1s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 55s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m15s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m47s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m4s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m55s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m21s
AI Code Review / AI Code Review (pull_request) Successful in 6m55s
CI/CD Pipeline / Validate - Style (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 6m0s
list() 对字符串逐字符拆分导致 pre_trusted_images 被读成 ['n','u','l','l']。
修复:
1. str 类型 → json.loads 解析为 list
2. list 类型 → 过滤长度≤5的短字符串元素(过滤字符拆分脏数据)
3. None/解析失败 → 返回 None

同时 _to_response 和 schema 已在 #2178 补 pre_trusted_images 字段。

Ref: #2175
2026-10-04 17:25:42 +08:00
xiaoxia 7a9a97b31a fix(api): add pre_trusted_images to API response schema (#2178)
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 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 / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (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 / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 23s
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 / 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 1m10s
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 / Build Staging API Image (push) Successful in 1m29s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m31s
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 Worker Image (push) Successful in 56s
CI/CD Pipeline / CI Gate (pull_request) Successful in 10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m32s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m43s
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 3m21s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m55s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m27s
CI/CD Pipeline / Validate - Style (push) Successful in 6m18s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m47s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m40s
AI Code Review / AI Code Review (pull_request) Successful in 7m2s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 2m41s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m15s
CI/CD Pipeline / Integration Tests (push) Successful in 8m26s
CI/CD Pipeline / Unit Tests (push) Successful in 13m26s
CI/CD Pipeline / Validate - Security (push) Successful in 15m32s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 17:09:10 +08:00
xiaoxia a6f89067e7 fix(viral_video): #2040 loader在api进程内DB热加载(懒建同步引擎) (#2176)
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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
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 push changed paths (push) Successful in 19s
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 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 35s
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 Staging Web Image (push) Successful in 36s
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 / 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 55s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 55s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 43s
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) Successful in 1m12s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m59s
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 / Integration Tests (push) Successful in 3m34s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m13s
CI/CD Pipeline / Validate - Style (push) Successful in 4m37s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m48s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m33s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m54s
AI Code Review / AI Code Review (pull_request) Successful in 6m46s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m30s
CI/CD Pipeline / Validate - Security (push) Successful in 10m55s
CI/CD Pipeline / Unit Tests (push) Successful in 11m17s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 16:07:25 +08:00
xiaoxia 718deb32b9 Merge pull request 'fix(#2174 P0): 信任链i2i改为t2i文生图,实测通过Seedance肖像审核' (#2175) from feat/2174-trust-chain-t2i into develop
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 (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 (push) Successful in 3s
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 / 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 / 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 Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 19s
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 / 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 55s
CI/CD Pipeline / Build Staging API Image (push) Successful in 53s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 45s
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 1m22s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 40s
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 2m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m13s
CI/CD Pipeline / Integration Tests (push) Successful in 4m18s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m29s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m19s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 5m21s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m22s
AI Code Review / AI Code Review (pull_request) Successful in 7m1s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m10s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m34s
CI/CD Pipeline / Validate - Security (push) Successful in 9m12s
CI/CD Pipeline / Unit Tests (push) Successful in 13m54s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
fix(#2174): 信任链从i2i改为t2i文生图,VLM提取人物特征→Seedream t2i纯文生图→Seedance i2v,实测通过肖像审核,人物保留度>90%
2026-10-04 15:49:02 +08:00
xiaoxia 054e81c3e7 feat(viral_video): #2040 Prompt模板系统(5套+DB配置化+seed) (#2174)
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 3s
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 / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 1m1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 8s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 49s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m9s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 53s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
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 / Integration Tests (push) Successful in 4m14s
PR Automation / Auto Merge on CI Green + Approved (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 / Validate - Python (mypy + alembic) (push) Successful in 4m27s
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 / PR Build API Image (pull_request) Successful in 1m26s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m48s
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 56s
CI/CD Pipeline / Validate - Style (push) Successful in 4m57s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m59s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m10s
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) 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 - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (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
AI Code Review / AI Code Review (pull_request) Has been cancelled
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 15:41:54 +08:00
CI Bot 07cf055a97 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 59s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m7s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m31s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m45s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m49s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m45s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 8m8s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m56s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 45s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 17m8s
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 / CI Gate (pull_request) Successful in 1s
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
2026-10-04 07:39:08 +00:00
xiaoxia 0e78f175fe fix(#2174 P0): 信任链从i2i改为t2i文生图——方舟实测验证通过
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
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 / Build Staging Web Image (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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m19s
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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m17s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m16s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m36s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m43s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 5m56s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
#2170/#2172的信任链用Seedream图生图(i2i,传reference_images=用户真人照),
实测产物不被Seedance信任,仍被400 portrait_intercept拦截。

方舟文档+实测确认:信任的是Seedream文生图(t2i)产物——纯prompt描述人物,
不传reference_images,产物是纯模型生成人像,同账号30天内可直接传Seedance。

改动:
- VLM prompt新增portrait_prompt字段(60-100字人物外貌描述)
- preheat_trust_chain签名从portrait_urls改为portrait_descriptions,t2i模式不传reference_images
- video_generation移除现场跑i2i逻辑,仅使用预热好的t2i结果;预热失败走#2166自动降级t2v
- 预热时机从VLM前改为VLM后(需要VLM输出的portrait_prompt),仍与文案阶段并行
- 单测适配:TestTrustChain全部改为pre_trusted_images路径验证

实测验证(充值后):
- Seedream flash t2i ~15s出图,人像prompt中英文混合写实风格
- Seedance 2.5 i2v用t2i产物URL → 成功出5s视频(120s)
- Seedance 2.0-mini i2v用t2i产物URL → 成功出5s视频
- 对照组直传用户真人照片 → 400 portrait_intercept(预期)
2026-10-04 15:31:38 +08:00
xiaoxia 371d1b9daf fix(#2173 P0): 文案生成超时修复+VLM快速失败+Seedream换flash模型 (#2173)
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 / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (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 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
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 / Frontend Lint (push) 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 / 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 / Check push changed paths (push) Successful in 20s
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 Worker 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 1m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m31s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m22s
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 / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 46s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m9s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m31s
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 / Integration Tests (push) Successful in 4m13s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m29s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m25s
CI/CD Pipeline / Validate - Style (push) Successful in 5m5s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m57s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 7m8s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 7m15s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 3m16s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m20s
CI/CD Pipeline / Validate - Security (push) Successful in 8m34s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m8s
CI/CD Pipeline / Unit Tests (push) Successful in 11m40s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 13:03:52 +08:00
xiaoxia 1a459d1ad2 perf(#2172): 信任链 Seedream i2i 与文案并行预热,缩短有参考图场景等待 (#2172)
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 (push) Successful in 3s
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 4s
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 / 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 / Frontend Lint (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 / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Web 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 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 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 / Check push changed paths (push) Successful in 58s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 52s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m12s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (push) Successful in 48s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m0s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m48s
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 3m16s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 3m53s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m12s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m30s
CI/CD Pipeline / Validate - Style (push) Successful in 4m34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m26s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m30s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m41s
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 / Staging E2E Tests (push) Failing after 3m51s
CI/CD Pipeline / Validate - Security (push) Successful in 8m45s
CI/CD Pipeline / Unit Tests (push) Successful in 11m33s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 12:19:12 +08:00
xiaoxia f097e16bc1 feat(observability): 豆包 LLM/VLM/Seedream/信任链加 elapsed 耗时日志 (#2171)
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 / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (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 / 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 / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (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 Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 18s
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 / 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 43s
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 1m32s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m12s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 59s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m5s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m25s
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 3m17s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m22s
CI/CD Pipeline / Integration Tests (push) Successful in 4m18s
CI/CD Pipeline / Validate - Style (push) Successful in 5m21s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m53s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m50s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m24s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m44s
AI Code Review / AI Code Review (pull_request) Successful in 10m36s
CI/CD Pipeline / Validate - Security (push) Successful in 11m46s
CI/CD Pipeline / Unit Tests (push) Successful in 15m24s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 11:26:45 +08:00
xiaoxia 69eea54cd2 Merge pull request 'feat(#2170): 方舟信任链——真人照片经 Seedream AI 化后走 Seedance reference_image' (#2170) from feature/2170-ark-trust-chain into develop
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 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 / PR Build Worker 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 / 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 / Check push changed paths (push) Successful in 25s
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 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 1m8s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m12s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m18s
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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m53s
CI/CD Pipeline / CI Gate (pull_request) Successful in 11s
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 / ACR Image Cleanup (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 / Build Staging Worker Image (push) Successful in 49s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 2m23s
CI/CD Pipeline / Integration Tests (push) Successful in 3m4s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m32s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 3m53s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m42s
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 - Security (push) Successful in 4m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m6s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m10s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m45s
CI/CD Pipeline / Unit Tests (push) Successful in 10m59s
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
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 16m53s
#2170 方舟信任链方案:真人照片经Seedream 5.0 Pro i2i AI化后走Seedance 2.5 reference_image;删除全部即梦代码和#2166 t2v降级逻辑
2026-10-04 10:16:21 +08:00
CI Bot b5cbc3b482 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
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 / Frontend Unit Tests (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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m25s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m47s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m59s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m11s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 3m31s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m57s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m40s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 14m55s
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
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 4m14s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m30s
2026-10-04 01:55:39 +00:00
saas-backend 9106b4de2e test(#2170): 修复信任链测试 time.time mock 被 logging 耗尽导致 StopIteration
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 / 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 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 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 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m50s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m6s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 3m25s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
CI (Python 3.12) 中 logging.LogRecord.__init__ 内部调 time.time(),
有限 iter 会被提前耗尽抛 StopIteration。改为无限 _fake_time 生成器,
并补充 3 个单测覆盖 line 537(无image_url走else分支) 和 lines 962-971
(通用异常重试 + 重试耗尽 break),diff 覆盖率 100%。
2026-10-04 09:51:51 +08:00
CI Bot 7d639d5f9a style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
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 / 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 2s
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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 46s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m7s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m27s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m0s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 4m34s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m25s
AI Code Review / AI Code Review (pull_request) Successful in 6m38s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m59s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 10m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m38s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 15m12s
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 / CI Gate (pull_request) Failing after 1s
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
2026-10-04 00:13:30 +00:00
saas-backend db6c237d68 test(#2170): 补充 Seedream 错误分支 + 信任链 partial 回退单测
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (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 / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m41s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m7s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m41s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m16s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m33s
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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-04 08:08:24 +08:00
CI Bot 7b68b94df6 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m42s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
AI Code Review / AI Code Review (pull_request) Successful in 6m57s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m58s
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 if frontend-only change (pull_request) Successful in 1s
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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m44s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m3s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m33s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 3m46s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m29s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 6m34s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 9m57s
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 / CI Gate (pull_request) Failing after 2s
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
2026-10-03 18:50:13 +00:00
saas-backend 8e19f24984 feat(#2170): 方舟信任链方案——真人照片经 Seedream AI 化后走 Seedance reference_image
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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
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 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 / 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 / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m17s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m28s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m2s
AI Code Review / AI Code Review (pull_request) Successful in 5m36s
CI/CD Pipeline / Unit Tests (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 / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- 删除即梦 cvtob 接入代码(jimeng_client.py / JIMENG_* 配置 / _call_jimeng_video_generation)
- 新增 DoubaoClient.image_generation:调用 Seedream 5.0 Pro (doubao-seedream-5-0-pro-260628) 文生图/图生图
- 信任链:有参考图时先经 Seedream 图生图 AI 化(保持五官特征),AI 产物作为 reference_image 传 Seedance
- 纯文字直传 Seedance 2.5;信任链强制走 reference_image 模式(非 first_frame),保留用户指定 ratio
- Seedream 失败自动回退原图直传;图片/视频错误分类统一,支持 last_image_error
- 删除 #2166 t2v 自动降级、#2169 jimeng 兜底逻辑
- config/base.py 新增 doubao_image_model/doubao_image_timeout,豆包模型升级到 seed-2-1 系列
- .env.example 清理 JIMENG_*,补全 VIDEO_*/IMAGE_* 配置
- points_rules.py 删除 jimeng-3.0 定价与模型配置
- 新增 10 个单测覆盖 Seedream 主路径 + 信任链 3 种场景;更新现有 mock
2026-10-04 02:44:08 +08:00
xiaoxia 866d71a431 feat(viral-video): #2169 接入即梦视觉API,真人参考图方舟50411自动切即梦兜底 (#2169)
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 / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
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 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 / Check push changed paths (push) Successful in 24s
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 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 Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 40s
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 / 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 Worker Image (push) Successful in 1m12s
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
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m27s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m39s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 4m13s
CI/CD Pipeline / Integration Tests (push) Successful in 4m20s
CI/CD Pipeline / Validate - Style (push) Successful in 5m3s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m38s
CI/CD Pipeline / Build Staging API Image (push) Successful in 4m37s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
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
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m34s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m8s
AI Code Review / AI Code Review (pull_request) Successful in 6m45s
CI/CD Pipeline / Validate - Security (push) Successful in 8m18s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m37s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m48s
CI/CD Pipeline / Unit Tests (push) Successful in 11m45s
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 / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Failing after 35m40s
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 01:48:59 +08:00
xiaoxia 042512a527 feat: 用户端套餐/积分包改读管理后台真实数据 (#2167)
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 / 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 / Build Staging API Image (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 / Validate - Style (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 - 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 / 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 push changed paths (push) Successful in 28s
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 / Deploy Staging (Watchtower auto-deploy) (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 1m17s
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 1m56s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m39s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m1s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m16s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m44s
CI/CD Pipeline / Validate - Style (push) Successful in 5m53s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m18s
CI/CD Pipeline / Integration Tests (push) Successful in 6m23s
AI Code Review / AI Code Review (pull_request) Successful in 6m54s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
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 Approve on CI Green (pull_request) Successful in 8m20s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 8m32s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m20s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m41s
CI/CD Pipeline / Validate - Security (push) Successful in 15m1s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 5m43s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 6m3s
CI/CD Pipeline / Unit Tests (push) Successful in 16m38s
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
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-04 01:01:02 +08:00
xiaoxia 3bb9c5dd4e Merge pull request 'fix(viral-video): #2165 视频生成详细错误日志+真人拦截友好提示' (#2166) from fix/2165-video-error-logging-and-user-message into develop
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 / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build 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 3s
CI/CD Pipeline / Build Staging Web Image (pull_request) 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 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 / 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 / Check push changed paths (push) Successful in 23s
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 / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m58s
CI/CD Pipeline / Validate - Style (push) Successful in 5m4s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m56s
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 / Integration Tests (push) Successful in 5m4s
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 5m5s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m33s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m34s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 3m36s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 5m26s
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
AI Code Review / AI Code Review (pull_request) Successful in 7m13s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m34s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 8m12s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m5s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m50s
CI/CD Pipeline / Validate - Security (push) Successful in 11m34s
CI/CD Pipeline / Unit Tests (push) Successful in 13m30s
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
CI/CD Pipeline / Staging E2E Tests (push) Failing after 29m30s
2026-10-04 00:08:32 +08:00
saas-backend c87810a4a6 fix(viral-video): 肖像/真人审核拦截时自动降级为纯文字t2v重试一次
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 if frontend-only change (pull_request) Successful in 2s
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 API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web 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 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 API 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 / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m0s
AI Code Review / AI Code Review (pull_request) Successful in 7m2s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 13m26s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 14m50s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 12m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 16m31s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 20m19s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 34m53s
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
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 55s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 5m55s
- _step_render 捕获portrait_intercept/真人/肖像/隐私/SensitiveContent等关键词错误
- 第一次带参考图/首帧/参考视频被审核拦截时,自动移除所有参考素材走纯t2v重试
- 保留reference_audios(TTS口型)不影响肖像审核
- 仍失败则抛具体错误信息(#2166已增强的错误透传)
- 解决用户上传真人产品图直接失败无法出片的问题
2026-10-03 23:25:58 +08:00
saas-backend 75ec9db439 fix(viral-video): #2165 视频生成错误详细日志+友好提示+真人拦截识别
- ai_client/dashscope_client 新增 last_video_error 字段,记录每次失败的
  error_code/user_message/status_code/detail/model 等结构化信息
- 新增 _classify_video_error 错误分类器,自动识别:
  - 真人肖像拦截 (portrait_intercept) → 提示用户移除真人图片
  - 鉴权失败 (auth_error) / 配额不足 (quota_exceeded) / 限流 (rate_limit)
  - 模型/Endpoint 不存在 (model_not_found) / 参数错误 (invalid_param)
  - 网络超时 (network_error) / 任务失败 (task_failed) / 未知 (unknown)
- call_video_generation 失败时通过 get_last_video_error() 暴露详细错误
- worker _step_render 不再笼统抛"返回为空",改为读取错误详情并展示具体用户提示
- 增强日志:完整 payload 打印(截断 prompt)、轮询 HTTP 错误记录完整 body、
  下载/超时时记录具体失败原因
- 修复重试策略:4xx 错误不再重试(参数/鉴权错误重试无意义),仅 5xx/网络错误重试
- DashScope 客户端同样增加 last_video_error 和错误分类,保持语义一致
- 新增单测覆盖:400真人拦截、401鉴权失败、轮询failed、ai_service错误透传、dashscope 401
2026-10-03 23:25:58 +08:00
xiaoxia 0d70074182 fix(ai-avatar): 对口型轮询timeout/间隔/总时长修复,单次超时不中断轮询 (#2165)
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 / 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 Worker 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 13s
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 1m56s
CI/CD Pipeline / Retag skipped Staging Worker 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 API Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m11s
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m40s
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 / Frontend Unit Tests (push) Successful in 4m21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m26s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m52s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (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 / PR Build Worker Image (pull_request) Successful in 4m29s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m50s
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
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 / CI Gate (pull_request) Successful in 2s
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 / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m21s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m33s
CI/CD Pipeline / Integration Tests (push) Successful in 13m38s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m9s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m57s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 17m56s
CI/CD Pipeline / Validate - Style (push) Successful in 19m1s
CI/CD Pipeline / Unit Tests (push) Successful in 21m51s
CI/CD Pipeline / Validate - Security (push) Successful in 38m56s
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 / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
fix(ai-avatar): 对口型轮询timeout/间隔/总时长修复

- getLipsyncJob/getRenderJob timeout 60s→300s(5分钟)
- 轮询间隔3s→5s
- 新增10分钟总轮询上限,超时提示去历史记录查看
- 单次请求失败(含timeout)改为console.warn继续下一轮,不中断轮询
2026-10-03 22:38:07 +08:00
xiaoxia 071a3707f4 Merge pull request 'feat: User实体补会员字段并映射(后台开会员用户端生效)' (#2164) from feat/member-fields-entity into develop
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 2s
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 / 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 4s
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 / Check push changed paths (push) Successful in 34s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (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 / 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 55s
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 Worker Image (pull_request) Successful in 2m35s
CI/CD Pipeline / Build Staging API Image (push) Successful in 42s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 34s
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 / CI Gate (pull_request) Successful in 2s
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 / Build Staging Worker Image (push) Successful in 35s
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 / 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 / Canary Release to Production (pull_request) Has been skipped
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 4m8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m9s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m38s
AI Code Review / AI Code Review (pull_request) Successful in 7m21s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m49s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 2m46s
CI/CD Pipeline / Integration Tests (push) Successful in 14m19s
CI/CD Pipeline / Validate - Style (push) Successful in 14m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 18m19s
CI/CD Pipeline / Unit Tests (push) Successful in 21m5s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 23m21s
CI/CD Pipeline / Validate - Security (push) Successful in 37m13s
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-03 21:13:03 +08:00
101 changed files with 12661 additions and 1095 deletions
+13 -4
View File
@@ -211,15 +211,24 @@ COSYVOICE_CLONE_MODEL=voice-enrollment
# 用于 AI 文案生成、智能剪辑等需要大模型能力的场景
DOUBAO_API_KEY=your-doubao-api-key
DOUBAO_MODEL=doubao-seed-1-6-250615
DOUBAO_FAST_MODEL=doubao-1-5-pro-32k-250115
DOUBAO_MODEL=doubao-seed-2-1-pro-260915
DOUBAO_FAST_MODEL=doubao-seed-2-1-lite-260915
DOUBAO_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
DOUBAO_TIMEOUT=30
DOUBAO_MAX_RETRIES=2
# 视觉模型:pro 精度高,lite 速度快(viral-video 商品识别默认用 lite 提速)
DOUBAO_VISION_MODEL=doubao-1-5-vision-pro-250328
DOUBAO_VISION_LITE_MODEL=doubao-1-5-vision-lite-250315
DOUBAO_VISION_MODEL=doubao-seed-2-1-pro-260915
DOUBAO_VISION_LITE_MODEL=doubao-seed-2-1-lite-260915
DOUBAO_VISION_USE_LITE=true
# Embedding 向量化模型
DOUBAO_EMBEDDING_MODEL=doubao-embedding-vision-251215
# 视频模型(Seedance 2.5,统一走方舟;真人参考图通过信任链自动 AI 化)
DOUBAO_VIDEO_MODEL=doubao-seedance-2-5-260628
DOUBAO_VIDEO_TIMEOUT=480
DOUBAO_VIDEO_POLL_INTERVAL=10
# 图片模型(Seedream 5.0 Pro,用于信任链真人 AI 化 + 文生图)
DOUBAO_IMAGE_MODEL=doubao-seedream-5-0-pro-260628
DOUBAO_IMAGE_TIMEOUT=120
# ==================== 积分/会员系统 (#1895) ====================
# 积分系统总开关:默认 false(暂停积分系统)。
+8
View File
@@ -1187,6 +1187,14 @@ jobs:
DOUBAO_MODEL: "${{ secrets.DOUBAO_MODEL }}"
DOUBAO_BASE_URL: "${{ secrets.DOUBAO_BASE_URL }}"
DOUBAO_VISION_MODEL: "${{ secrets.DOUBAO_VISION_MODEL }}"
DOUBAO_VISION_LITE_MODEL: "${{ secrets.DOUBAO_VISION_LITE_MODEL }}"
DOUBAO_VISION_USE_LITE: "${{ secrets.DOUBAO_VISION_USE_LITE }}"
DOUBAO_IMAGE_MODEL: "${{ secrets.DOUBAO_IMAGE_MODEL }}"
DOUBAO_IMAGE_SIZE: "${{ secrets.DOUBAO_IMAGE_SIZE }}"
DOUBAO_IMAGE_TIMEOUT: "${{ secrets.DOUBAO_IMAGE_TIMEOUT }}"
DOUBAO_FAST_MODEL: "${{ secrets.DOUBAO_FAST_MODEL }}"
DOUBAO_TIMEOUT: "${{ secrets.DOUBAO_TIMEOUT }}"
DOUBAO_MAX_RETRIES: "${{ secrets.DOUBAO_MAX_RETRIES }}"
WECHAT_APP_ID: "${{ secrets.WECHAT_APP_ID }}"
WECHAT_APP_SECRET: "${{ secrets.WECHAT_APP_SECRET }}"
TIKHUB_API_KEY: "${{ secrets.TIKHUB_API_KEY }}"
+2
View File
@@ -0,0 +1,2 @@
Mon Oct 5 04:09:11 PM CST 2026
2198 lite/pro并行竞速 (commit 9699a1f) — CI rebuild trigger Mon Oct 5 08:09:11 AM UTC 2026
@@ -0,0 +1,31 @@
"""viral_video_jobs 增加 pre_trusted_images 列(信任链Seedream预热结果)
Revision ID: 094_viral_video_pre_trusted
Revises: 093_viral_video_pricing_points_float
Create Date: 2026-10-04
"""
import sqlalchemy as sa
from alembic import op
revision = "094_viral_video_pre_trusted"
down_revision = "093"
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
inspector = sa.inspect(conn)
cols = {c["name"] for c in inspector.get_columns("viral_video_jobs")}
if "pre_trusted_images" not in cols:
op.add_column("viral_video_jobs", sa.Column("pre_trusted_images", sa.Text(), nullable=True))
def downgrade() -> None:
conn = op.get_bind()
inspector = sa.inspect(conn)
cols = {c["name"] for c in inspector.get_columns("viral_video_jobs")}
if "pre_trusted_images" in cols:
op.drop_column("viral_video_jobs", "pre_trusted_images")
@@ -0,0 +1,102 @@
"""爆款视频 Prompt 模板配置表(#2040)。
086 曾预留同名旧表(id varchar / content / variables json),从未被业务使用;
本迁移将其替换为 #2040 新结构。
Revision ID: 095_viral_video_prompt_templates
Revises: 094_viral_video_pre_trusted
Create Date: 2026-10-04
"""
import sqlalchemy as sa
from alembic import op
revision = "095_viral_video_prompt_templates"
down_revision = "094_viral_video_pre_trusted"
branch_labels = None
depends_on = None
def _table_exists(conn, name: str) -> bool:
return name in sa.inspect(conn).get_table_names()
def upgrade() -> None:
conn = op.get_bind()
# 086 预留的旧结构表:先删除(无业务数据、无任何引用)
if _table_exists(conn, "viral_video_prompt_templates"):
op.drop_table("viral_video_prompt_templates")
op.create_table(
"viral_video_prompt_templates",
sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
sa.Column("name", sa.String(128), nullable=False),
sa.Column("prompt_type", sa.String(32), nullable=False),
sa.Column("version", sa.Integer, nullable=False, server_default="1"),
sa.Column("system_prompt", sa.Text, nullable=False),
sa.Column("user_prompt_template", sa.Text, nullable=False),
sa.Column("example_output", sa.Text, nullable=True),
sa.Column("is_active", sa.Boolean, nullable=False, server_default=sa.text("true")),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
server_default=sa.func.now(),
nullable=False,
),
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
server_default=sa.func.now(),
nullable=False,
),
)
op.create_index(
"ix_vvpt_type_active",
"viral_video_prompt_templates",
["prompt_type", "is_active"],
)
op.create_index(
"uq_vvpt_type_version",
"viral_video_prompt_templates",
["prompt_type", "version"],
unique=True,
)
def downgrade() -> None:
conn = op.get_bind()
if _table_exists(conn, "viral_video_prompt_templates"):
op.drop_index("uq_vvpt_type_version", table_name="viral_video_prompt_templates")
op.drop_index("ix_vvpt_type_active", table_name="viral_video_prompt_templates")
op.drop_table("viral_video_prompt_templates")
# 恢复 086 的旧预留结构
op.create_table(
"viral_video_prompt_templates",
sa.Column("id", sa.String(36), primary_key=True),
sa.Column("prompt_type", sa.String(50), nullable=False, index=True),
sa.Column("name", sa.String(200), nullable=False),
sa.Column("content", sa.Text, nullable=False, server_default=""),
sa.Column("variables", sa.JSON, nullable=False, server_default="[]"),
sa.Column("version", sa.Integer, nullable=False, server_default="1"),
sa.Column(
"is_active",
sa.Boolean,
nullable=False,
server_default=sa.text("true"),
index=True,
),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
sa.Column(
"updated_at",
sa.DateTime(timezone=True),
nullable=False,
server_default=sa.func.now(),
),
)
+61
View File
@@ -0,0 +1,61 @@
"""功能计费积分字段(爆款/对口型/智能剪辑 DB 化计费)。
给 gpu_lipsync_tasks / generation_tasks / lipsync_jobs 三张表加积分字段:
- credits_prepaid: 提交任务时预扣积分
- credits_cost: 最终结算积分
- credits_transaction_id: 预扣流水 ID
注意:feature_pricing_configs 配置表由 xiaoxia-admin 侧 migration 建立,
本仓库只读,不在此创建。
Revision ID: 096_feature_billing_fields
Revises: 095_viral_video_prompt_templates
Create Date: 2026-10-05
"""
import sqlalchemy as sa
from alembic import op
revision = "096_feature_billing_fields"
down_revision = "095_viral_video_prompt_templates"
branch_labels = None
depends_on = None
_TABLES = ("gpu_lipsync_tasks", "generation_tasks", "lipsync_jobs")
_COLUMNS = (
("credits_prepaid", sa.Float(), "0"),
("credits_cost", sa.Float(), "0"),
("credits_transaction_id", sa.String(36), ""),
)
def _table_exists(conn, name: str) -> bool:
return name in sa.inspect(conn).get_table_names()
def upgrade() -> None:
conn = op.get_bind()
for table in _TABLES:
if not _table_exists(conn, table):
continue
existing = {c["name"] for c in sa.inspect(conn).get_columns(table)}
for col_name, col_type, default in _COLUMNS:
if col_name in existing:
continue
op.add_column(
table,
sa.Column(col_name, col_type, nullable=False, server_default=default),
)
def downgrade() -> None:
conn = op.get_bind()
for table in _TABLES:
if not _table_exists(conn, table):
continue
existing = {c["name"] for c in sa.inspect(conn).get_columns(table)}
for col_name, _col_type, _default in _COLUMNS:
if col_name not in existing:
continue
op.drop_column(table, col_name)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,222 @@
# -*- coding: utf-8 -*-
"""099: AI 模型路由层 seed — 补齐缺失模型和能力配置.
幂等:所有 INSERT 先检查存在性。
- ai_models: 补齐 qwen3.7-plus, seedream, seedance, embedding, wan3.0 等
- ai_capability_configs: 补齐 image_generation, video_generation, embedding
- 更新已有 capability 的 lite_model_id
"""
import json
import sqlalchemy as sa
from alembic import op
revision = "099_ai_model_router_seed"
down_revision = "098_viral_video_image_analysis_v5"
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
# CI 环境下 ai_models 表可能尚未创建(由 ORM 自动建表,非 migration)
# 如果表不存在则跳过 seed,由应用启动时 ORM 建表后首次访问时生效
table_check = conn.execute(sa.text("SELECT to_regclass('public.ai_models')")).scalar()
if not table_check:
# ai_models 表不存在,跳过所有 seed(CI 环境)
return
# ── 1. 补齐 ai_models 缺失记录 ────────────────────────────────────────────
existing_models = {
row[0]
for row in conn.execute(
sa.text("SELECT model_key FROM ai_models WHERE deleted_at IS NULL")
).fetchall()
}
# 从已有 active 记录获取 API key(复用,不硬编码)
dashscope_key_row = conn.execute(
sa.text(
"SELECT api_key FROM ai_models WHERE provider='dashscope' AND deleted_at IS NULL AND api_key IS NOT NULL AND api_key != '' LIMIT 1"
)
).first()
dashscope_key = dashscope_key_row[0] if dashscope_key_row else ""
volcengine_key_row = conn.execute(
sa.text(
"SELECT api_key FROM ai_models WHERE provider='volcengine' AND deleted_at IS NULL AND api_key IS NOT NULL AND api_key != '' LIMIT 1"
)
).first()
volcengine_key = volcengine_key_row[0] if volcengine_key_row else ""
new_models = [
{
"model_key": "qwen3.7-plus",
"name": "通义千问3.7 Plus(VLM 兜底)",
"provider": "dashscope",
"api_key": dashscope_key,
"api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"description": "阿里云百炼 Qwen3.7 Plus 多模态模型,用于 VLM 兜底分析",
},
{
"model_key": "doubao-seedream-5-0-flash-260915",
"name": "Seedream 5.0 Flash(图片生成)",
"provider": "volcengine",
"api_key": volcengine_key,
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"description": "火山引擎 Seedream 5.0 Flash 文生图模型",
},
{
"model_key": "doubao-seedance-2-5-260628",
"name": "Seedance 2.5(视频生成)",
"provider": "volcengine",
"api_key": volcengine_key,
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"description": "火山引擎 Seedance 2.5 图/文生视频模型",
},
{
"model_key": "doubao-embedding-vision-251215",
"name": "豆包多模态向量嵌入",
"provider": "volcengine",
"api_key": volcengine_key,
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"description": "火山引擎豆包多模态向量嵌入模型",
},
{
"model_key": "wan3.0-video",
"name": "Wan 3.0 视频生成",
"provider": "dashscope",
"api_key": dashscope_key,
"api_base": "https://dashscope.aliyuncs.com/api/v1",
"description": "阿里云百炼 Wan 3.0 视频生成模型",
},
{
"model_key": "doubao-seed-2-1-pro-260915",
"name": "豆包 Seed 2.1 Pro(高精度推理)",
"provider": "volcengine",
"api_key": volcengine_key,
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"description": "火山引擎豆包 Seed 2.1 Pro 深度思考+多模态",
},
]
for m in new_models:
if m["model_key"] not in existing_models:
conn.execute(
sa.text(
"""
INSERT INTO ai_models (id, name, provider, model_key, api_key, api_base, description, status, is_default, usage_today, created_at, updated_at)
VALUES (gen_random_uuid()::text, :name, :provider, :model_key, :api_key, :api_base, :description, 'active', false, 0, now(), now())
"""
),
m,
)
# ── 2. 补齐 ai_capability_configs 缺失项 ──────────────────────────────────
cap_table_check = conn.execute(sa.text("SELECT to_regclass('public.ai_capability_configs')")).scalar()
if not cap_table_check:
return
existing_caps = {
row[0]
for row in conn.execute(
sa.text("SELECT capability_key FROM ai_capability_configs")
).fetchall()
}
def _get_model_id(model_key: str) -> str | None:
row = conn.execute(
sa.text(
"SELECT id FROM ai_models WHERE model_key = :key AND deleted_at IS NULL AND status = 'active' LIMIT 1"
),
{"key": model_key},
).first()
return row[0] if row else None
# image_generation
if "image_generation" not in existing_caps:
mid = _get_model_id("doubao-seedream-5-0-flash-260915")
if mid:
conn.execute(
sa.text(
"""
INSERT INTO ai_capability_configs (id, capability_key, capability_name, primary_model_id, timeout_seconds, max_retries, concurrency, extra_params, is_enabled, created_at, updated_at)
VALUES (gen_random_uuid()::text, :ck, :cn, :pm, 60, 1, 2, :ep, true, now(), now())
"""
),
{
"ck": "image_generation",
"cn": "图片生成(Seedream)",
"pm": mid,
"ep": json.dumps({"size": "1K"}),
},
)
# video_generation
if "video_generation" not in existing_caps:
mid = _get_model_id("doubao-seedance-2-5-260628")
fb_mid = _get_model_id("wan3.0-video")
if mid:
conn.execute(
sa.text(
"""
INSERT INTO ai_capability_configs (id, capability_key, capability_name, primary_model_id, fallback_model_id, timeout_seconds, max_retries, concurrency, extra_params, is_enabled, created_at, updated_at)
VALUES (gen_random_uuid()::text, :ck, :cn, :pm, :fm, 600, 1, 1, :ep, true, now(), now())
"""
),
{
"ck": "video_generation",
"cn": "视频生成(Seedance/Wan)",
"pm": mid,
"fm": fb_mid,
"ep": json.dumps({}),
},
)
# embedding
if "embedding" not in existing_caps:
mid = _get_model_id("doubao-embedding-vision-251215")
if mid:
conn.execute(
sa.text(
"""
INSERT INTO ai_capability_configs (id, capability_key, capability_name, primary_model_id, timeout_seconds, max_retries, concurrency, extra_params, is_enabled, created_at, updated_at)
VALUES (gen_random_uuid()::text, :ck, :cn, :pm, 30, 2, 5, :ep, true, now(), now())
"""
),
{
"ck": "embedding",
"cn": "向量嵌入",
"pm": mid,
"ep": json.dumps({}),
},
)
# ── 3. 更新 image_analysis 的 lite_model_id ─────────────────────────────
lite_model_id = _get_model_id("qwen3.8-flash")
if lite_model_id:
conn.execute(
sa.text(
"UPDATE ai_capability_configs SET lite_model_id = :lite WHERE capability_key = 'image_analysis' AND lite_model_id IS NULL"
),
{"lite": lite_model_id},
)
def downgrade() -> None:
conn = op.get_bind()
# 安全检查表是否存在
table_check = conn.execute(sa.text("SELECT to_regclass('public.ai_models')")).scalar()
if not table_check:
return
conn.execute(
sa.text("DELETE FROM ai_capability_configs WHERE capability_key IN ('image_generation', 'video_generation', 'embedding')")
)
conn.execute(
sa.text(
"DELETE FROM ai_models WHERE model_key IN ('qwen3.7-plus', 'doubao-seedream-5-0-flash-260915', 'doubao-seedance-2-5-260628', 'doubao-embedding-vision-251215', 'wan3.0-video', 'doubao-seed-2-1-pro-260915') AND deleted_at IS NULL"
)
)
@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
"""100: 修正已有 capability 的模型绑定.
幂等:仅当 primary_model_id 当前绑定到旧模型 (doubao-seed-1-6) 时才更新,
避免覆盖用户在后台的自定义配置。
- 更新 5 个 LLM capability (intent_parsing, copy_fusion, storyboard, copy_review, asset_classify)
的 primary_model_id 从 doubao-seed-1-6 改为 doubao-seed-2-1-pro-260915
- 更新 image_analysis 的 primary/lite/fallback 模型绑定
"""
import sqlalchemy as sa
from alembic import op
revision = "100_fix_capability_model_bindings"
down_revision = "099_ai_model_router_seed"
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
# Check tables exist
table_check = conn.execute(sa.text("SELECT to_regclass('public.ai_models')")).scalar()
if not table_check:
return
config_table_check = conn.execute(sa.text("SELECT to_regclass('public.ai_capability_configs')")).scalar()
if not config_table_check:
return
# Look up model IDs by model_key (not hardcoded UUIDs)
pro_model_row = conn.execute(
sa.text(
"SELECT id FROM ai_models WHERE model_key = 'doubao-seed-2-1-pro-260915' AND deleted_at IS NULL LIMIT 1"
)
).first()
if not pro_model_row:
return
pro_model_id = pro_model_row[0]
old_model_row = conn.execute(
sa.text("SELECT id FROM ai_models WHERE model_key = 'doubao-seed-1-6-250615' LIMIT 1")
).first()
old_model_id = old_model_row[0] if old_model_row else None
llm_capabilities = [
"intent_parsing",
"copy_fusion",
"storyboard",
"copy_review",
"asset_classify",
]
for cap_key in llm_capabilities:
if old_model_id:
conn.execute(
sa.text(
"UPDATE ai_capability_configs SET primary_model_id = :new_id, updated_at = NOW() "
"WHERE capability_key = :cap_key AND primary_model_id = :old_id"
),
{"new_id": pro_model_id, "old_id": old_model_id, "cap_key": cap_key},
)
# Update image_analysis
qwen38_row = conn.execute(
sa.text("SELECT id FROM ai_models WHERE model_key = 'qwen3.8-flash' AND deleted_at IS NULL LIMIT 1")
).first()
qwen37_row = conn.execute(
sa.text("SELECT id FROM ai_models WHERE model_key = 'qwen3.7-plus' AND deleted_at IS NULL LIMIT 1")
).first()
if qwen38_row and qwen37_row:
qwen38_id = qwen38_row[0]
qwen37_id = qwen37_row[0]
current_ia = conn.execute(
sa.text(
"SELECT primary_model_id, lite_model_id, fallback_model_id "
"FROM ai_capability_configs WHERE capability_key = 'image_analysis'"
)
).first()
if current_ia:
current_primary, current_lite, current_fallback = current_ia
updates = {}
if current_primary != qwen38_id:
updates["primary_model_id"] = qwen38_id
if current_lite != qwen38_id:
updates["lite_model_id"] = qwen38_id
if current_fallback != qwen37_id:
updates["fallback_model_id"] = qwen37_id
if updates:
set_clause = ", ".join([f"{k} = :{k}" for k in updates.keys()])
set_clause += ", updated_at = NOW()"
updates["cap_key"] = "image_analysis"
conn.execute(
sa.text(f"UPDATE ai_capability_configs SET {set_clause} WHERE capability_key = :cap_key"),
updates,
)
def downgrade() -> None:
pass
@@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
"""101: 补齐 qwen-vl-plus 视觉模型并修正 image_analysis 绑定与 max_tokens.
背景:
- qwen-vl-plus 做图片识别时返回 JSON 约 500-600 tokens,旧硬编码
max_tokens=350 导致 JSON 被截断、解析失败返回"未识别"。
- 代码侧已移除硬编码,改由 capability 的 DB 配置决定 max_tokens。
幂等:
- qwen-vl-plus 已存在则不插入;
- 仅当 image_analysis 当前 primary_model 不是 qwen-vl-plus 时才更新绑定,
避免覆盖后台手动配置。
"""
import sqlalchemy as sa
from alembic import op
revision = "101_qwen_vl_plus_and_max_tokens"
down_revision = "100_fix_capability_model_bindings"
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
models_table = conn.execute(sa.text("SELECT to_regclass('public.ai_models')")).scalar()
if not models_table:
return
caps_table = conn.execute(sa.text("SELECT to_regclass('public.ai_capability_configs')")).scalar()
if not caps_table:
return
# ── c. 补全其他 capability 的 max_tokens 默认值(幂等)──────────────────
# 放在 image_analysis 特定逻辑之前,确保任何分支 return 都不会跳过本段。
# 仅在当前值为 NULL 或过小 (<100) 时更新,不覆盖已有合理配置。
# embedding / tts / voice_clone 不走 chat 接口,无需设置。
default_max_tokens = {
"intent_parsing": 500,
"copy_fusion": 2500,
"storyboard": 4000,
"copy_review": 1000,
"asset_classify": 500,
"image_generation": 500,
"video_generation": 500,
}
for cap_key, mt in default_max_tokens.items():
conn.execute(
sa.text(
"UPDATE ai_capability_configs "
"SET max_tokens = :mt, updated_at = now() "
"WHERE capability_key = :key "
"AND (max_tokens IS NULL OR max_tokens < 100)"
),
{"mt": mt, "key": cap_key},
)
# ── a. 确保 qwen-vl-plus 模型存在 ────────────────────────────────────────
conn.execute(sa.text("""
INSERT INTO ai_models (id, name, provider, model_key, api_key, api_base,
description, status, is_default, usage_today,
created_at, updated_at)
SELECT gen_random_uuid()::text,
'通义千问VL Plus',
'dashscope',
'qwen-vl-plus',
COALESCE(
(SELECT api_key FROM ai_models
WHERE provider = 'dashscope' AND deleted_at IS NULL
AND api_key IS NOT NULL AND api_key != ''
LIMIT 1),
''
),
'https://dashscope.aliyuncs.com/compatible-mode/v1',
'阿里云视觉理解模型(图片识别/分析)',
'active', false, 0, now(), now()
WHERE NOT EXISTS (
SELECT 1 FROM ai_models
WHERE model_key = 'qwen-vl-plus' AND deleted_at IS NULL
)
"""))
qwen_vl_row = conn.execute(
sa.text(
"SELECT id FROM ai_models WHERE model_key = 'qwen-vl-plus' "
"AND deleted_at IS NULL AND status = 'active' LIMIT 1"
)
).first()
if not qwen_vl_row:
return
qwen_vl_id = qwen_vl_row[0]
qwen37_row = conn.execute(
sa.text(
"SELECT id FROM ai_models WHERE model_key = 'qwen3.7-plus' "
"AND deleted_at IS NULL AND status = 'active' LIMIT 1"
)
).first()
qwen37_id = qwen37_row[0] if qwen37_row else None
# ── b. 仅当当前 primary 不是 qwen-vl-plus 时修正绑定与 max_tokens ───────
current = conn.execute(
sa.text(
"SELECT primary_model_id, lite_model_id, fallback_model_id, max_tokens "
"FROM ai_capability_configs WHERE capability_key = 'image_analysis'"
)
).first()
if current is None:
# capability 不存在则创建
conn.execute(
sa.text("""
INSERT INTO ai_capability_configs
(id, capability_key, capability_name, primary_model_id,
lite_model_id, fallback_model_id, timeout_seconds,
max_retries, max_tokens, concurrency, extra_params,
is_enabled, created_at, updated_at)
VALUES (gen_random_uuid()::text, 'image_analysis', '图片分析',
:primary, :primary, :fallback, 30, 1, 1000, 2,
'{}'::jsonb, true, now(), now())
"""),
{"primary": qwen_vl_id, "fallback": qwen37_id},
)
return
current_primary = current[0]
if current_primary == qwen_vl_id:
# 已经绑定 qwen-vl-plus:视为后台/数据迁移已处理,不覆盖任何配置
return
set_parts = [
"primary_model_id = :vl_id",
"lite_model_id = :vl_id",
"max_tokens = 1000",
"updated_at = now()",
]
params: dict = {"vl_id": qwen_vl_id}
if qwen37_id is not None:
set_parts.insert(2, "fallback_model_id = :qwen37_id")
params["qwen37_id"] = qwen37_id
conn.execute(
sa.text(
"UPDATE ai_capability_configs SET " + ", ".join(set_parts) + " WHERE capability_key = 'image_analysis'"
),
params,
)
def downgrade() -> None:
pass
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""102: image_analysis max_tokens 1200 -> 1500.
v6 prompt 更长、字段更多,旧 max_tokens 容易截断 JSON。
仅在 image_analysis 当前 max_tokens < 1500 时更新(幂等,不覆盖后台已调到 >=1500 的配置)。
"""
import sqlalchemy as sa
from alembic import op
revision = "102_image_analysis_max_tokens_1500"
down_revision = "101_qwen_vl_plus_and_max_tokens"
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
caps_table = conn.execute(sa.text("SELECT to_regclass('public.ai_capability_configs')")).scalar()
if not caps_table:
return
conn.execute(
sa.text(
"UPDATE ai_capability_configs "
"SET max_tokens = 1500, updated_at = now() "
"WHERE capability_key = 'image_analysis' "
"AND (max_tokens IS NULL OR max_tokens < 1500)"
)
)
def downgrade() -> None:
pass
@@ -0,0 +1,194 @@
# -*- coding: utf-8 -*-
"""image_analysis v7 prompt + max_tokens 3000 + max_retries 3
Revision ID: 103_v7_prompt_and_tokens_3000
Revises: 102_image_analysis_max_tokens_1500
Create Date: 2026-10-07
变更:
1. 插入v7精简prompt(~1KB,v6 ~4.5KB,删除few-shot/冗长规则,减少输出token占用),设为active
2. v6停用(is_active=False),保留历史
3. image_analysis capability: max_tokens 1500→3000,max_retries 1→3
ai_capability_configs 由应用 create_all 创建,全新 alembic-only 库可能不存在,
故第3步做 to_regclass 守卫(同 102)。
"""
from sqlalchemy import text
from alembic import op
revision = "103_v7_prompt_and_tokens_3000"
down_revision = "102_image_analysis_max_tokens_1500"
branch_labels = None
depends_on = None
V7_SYSTEM = """# 角色
你是一位专业的图片分析师,擅长准确识别图片中的场景、人物、物体、文字、氛围。
# 任务
对用户上传的图片逐张分析,描述你看到的内容,输出JSON格式。
## 技能
### 技能1:判断图片类型
判断图片属于哪种类型,type字段填对应的英文值:
- 商品图(product):单个或多个商品、产品包装
- 门店场景图(store):店铺内部、门头招牌、货架陈列
- 人物图(person):人物形象、穿搭造型、肖像照片
- 风景图(scene):风景、动物、美食、街景
- 其他(other):以上都不是
### 技能2:描述通用信息
不管什么图都要描述:
- type:图片类型,填product/store/person/scene/other其中一个
- scene:一句话描述场景,例如"理疗养生店内部,摆着多张理疗床和产品货架"
- mood:整体氛围,2-4个词,例如"整洁专业"、"热闹温馨"
- colors:主要颜色,最多5个,写具体颜色名(亮红色/米白色/深蓝色,不写笼统的红色蓝色)
- visible_text:图片里看到的文字,说明什么字、在什么位置,最多5条;没看到就空数组
- lighting:光线情况,例如"明亮柔光"、"自然光"、"室内暖黄灯"
- composition:怎么拍的,例如"居中特写"、"中景平视"、"俯拍"
- has_person:有没有人,true或false
### 技能3:描述门店场景
如果是门店场景图(type="store"),还要描述:
- store_type:什么类型的店,例如"养生馆"、"便利店"、"餐饮店"、"母婴店"
- brand_signage:招牌上写了什么字、有什么品牌标识
- visual_elements:看到哪些显眼的东西(招牌样式、灯光、货架、商品陈列、海报、收银台等),最多8个
- product_categories:看到哪些品类的商品,例如"饮料零食"、"养生产品"
- promotion_elements:有没有促销活动(打折海报、满减吊旗等),没有就空数组
- atmosphere:店内什么氛围,例如"亲民生活化"、"老字号专业感"
- cleanliness:店内干净程度,例如"干净整洁"、"货架整齐"
- 看到顾客或店员要描述他们在做什么,has_person填true
### 技能4:描述商品
如果是商品图(type="product"),逐个商品描述:
- product_name:商品名称,尽量具体,例如"OMO奥妙除菌除螨洗衣液";看不出来填null
- brand:什么牌子,看不出来填null
- category:类目,从以下选一个:服饰鞋包/美妆/数码/食品/家居清洁/母婴/配饰/其他
- package_type:什么包装,例如"瓶装"、"盒装"、"罐装"、"袋装"、"多瓶装"
- package_color:包装主要颜色,写具体色(亮红色不写红色)
- body_shape:瓶身或包装形状,例如"圆润胖瓶"、"竖款带把手瓶身"
- label_design:标签设计,例如"红色标签印白色品牌logo"
- key_text_on_package:包装上最显眼的文字(品牌名、功能词、卖点词),最多5个
- product_features:包装特征,3-6个短语,包含颜色、瓶盖、形状、标签图案
- key_selling_points:核心卖点,1-3个短语
### 技能5:描述人物
如果是人物图(type="person"),描述:
- person_count:几个人
- gender:性别(男/女/无法判断)
- age_range:年龄段(儿童/青少年/青年/中年/老年/无法判断)
- outfit_style:穿搭风格,例如"休闲日常"、"通勤商务"、"街头潮流"
- upper_wear:上装(颜色+款式+材质),穿裙装不填
- lower_wear:下装(颜色+款式+版型),穿裙装不填
- dress_wear:裙装描述,穿上下装不填
- outerwear:外套
- shoes:鞋子
- bag:包袋,没有填null
- accessories:配饰(眼镜/帽子/项链/耳环/手表/手链/围巾/腰带等),没有填空数组
- hairstyle:发型
- makeup:妆容,男生或看不出填null
- expression:表情,例如"微笑看镜头"、"冷酷无表情"
- pose:姿势动作,例如"身直立正对镜头"、"单手撩发"
- body_type:身材,例如"纤细苗条"、"高挑身材"、"丰满匀称"
- portrait_prompt:80-150字详细描述人物形象(后面用来AI生成肖像图),要写清年龄段、穿搭完整细节、发型发色、妆容、表情、姿势、场景、光线、风格感觉,语言要有画面感
### 技能6:描述风景
如果是风景图(type="scene"),描述:
- scene_type:什么场景,例如"自然风景"、"城市街景"、"动物"、"美食"
- main_subject:画面主体是什么
- key_elements:关键元素,最多8个
- environment_objects:周围环境物体,最多8个
- atmosphere:整体氛围,例如"秋日慵懒氛围感"、"清新自然氧气感"
- 有人物就描述人物特征
## 限制
- 只输出JSON,不要任何解释文字,不要markdown代码块包裹,不要写"好的""以下是分析结果"这种废话
- 颜色写具体色调(亮红色/米白色/深蓝色/翠绿色),不写笼统词汇
- 瓶身、包装、招牌上的文字尽量识别出来(品牌名、功能词、卖点词)
- 多个商品、多个人物分开描述,不要合并
- 看不出来、不确定的字段填null或空数组,布尔值填true/false,绝对不要瞎编
- 确保JSON格式合法,所有大括号、中括号、引号正确闭合
- 数组字段控制数量:colors最多5个,visible_text最多5条,visual_elements最多8个,accessories最多10个"""
V7_USER = "请分析这张图片,按系统消息的JSON结构输出。"
def _capability_table_exists(bind) -> bool:
return bool(bind.execute(text("SELECT to_regclass('public.ai_capability_configs')")).scalar())
def upgrade() -> None:
bind = op.get_bind()
# 1. 停用旧的active image_analysis prompt(含v6)
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = FALSE "
"WHERE prompt_type = 'image_analysis' AND is_active = TRUE"
)
)
# 2. 幂等插入v7(存在则更新并重新激活)
existing = bind.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type = 'image_analysis' AND version = 7")
).fetchone()
if existing:
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE, "
"system_prompt = :sys, user_prompt_template = :usr, "
"name = 'v7 精简结构化分析', updated_at = NOW() "
"WHERE prompt_type = 'image_analysis' AND version = 7"
),
{"sys": V7_SYSTEM, "usr": V7_USER},
)
else:
bind.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(prompt_type, version, name, system_prompt, user_prompt_template, "
"is_active, created_at, updated_at) "
"VALUES ('image_analysis', 7, 'v7 精简结构化分析', "
":sys, :usr, TRUE, NOW(), NOW())"
),
{"sys": V7_SYSTEM, "usr": V7_USER},
)
# 3. capability max_tokens=3000、max_retries=3(表不存在则跳过)
if _capability_table_exists(bind):
bind.execute(
text(
"UPDATE ai_capability_configs SET max_tokens = 3000, "
"updated_at = NOW() "
"WHERE capability_key = 'image_analysis' AND "
"(max_tokens IS NULL OR max_tokens < 3000)"
)
)
bind.execute(
text(
"UPDATE ai_capability_configs SET max_retries = 3, updated_at = NOW() "
"WHERE capability_key = 'image_analysis' AND "
"(max_retries IS NULL OR max_retries < 3)"
)
)
def downgrade() -> None:
bind = op.get_bind()
# 删除v7
bind.execute(
text("DELETE FROM viral_video_prompt_templates " "WHERE prompt_type = 'image_analysis' AND version = 7")
)
# 恢复v6为active
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE "
"WHERE prompt_type = 'image_analysis' AND version = 6"
)
)
# tokens/retries回退
if _capability_table_exists(bind):
bind.execute(
text(
"UPDATE ai_capability_configs SET max_tokens = 1500, max_retries = 1, "
"updated_at = NOW() WHERE capability_key = 'image_analysis'"
)
)
@@ -0,0 +1,242 @@
# -*- coding: utf-8 -*-
"""image_analysis v8 prompt + storyboard v3 prompt - 用户端展示格式 markdown 控制
Revision ID: 104_v8_display_markdown
Revises: 103_v7_prompt_and_tokens_3000
Create Date: 2026-10-07
变更:
1. image_analysis v8: 在 v7 基础上 system_prompt 末尾追加「## 用户端展示格式」章节,
要求 VLM 在每张图的 JSON 里输出 summary_markdown 字段(markdown 格式的图片描述),
v8 设 is_active=true,v7 设 is_active=false。
2. storyboard v3: 在 v2 基础上 system_prompt 追加要求 LLM 在 copy_result 中
输出 copy_display_markdown 字段(markdown 格式的完整文案展示),
v3 设 is_active=true,v2 设 is_active=false。
"""
from sqlalchemy import text
from alembic import op
revision = "104_v8_display_markdown"
down_revision = "103_v7_prompt_and_tokens_3000"
branch_labels = None
depends_on = None
# ── v8 追加的 system prompt 内容 ──────────────────────────────────────
V8_SYSTEM_APPEND = """
## 用户端展示格式
对于每张分析的图片,在 JSON 中额外输出一个 **summary_markdown** 字段,用 markdown 格式写出给用户看的图片描述。
格式要求(根据图片类型自适应):
**商品图(type=product)**示例:
### 商品名称
**品牌**:品牌名 | **类目**:服饰鞋包/美妆/数码/...
**核心特征**
- 特征1:描述
- 特征2:描述
**外观**:颜色+材质+设计描述
**包装**:包装类型描述
**文字信息**:包装上看到的文字
**门店场景图(type=store)**示例:
### 门店名称/类型
**类型**:奶茶店/便利店/养生馆/...
**品牌标识**:招牌文字描述
**环境氛围**:店内整体感觉
**陈列亮点**
- 亮点1
- 亮点2
**氛围**:亲民/专业/时尚/...
**人物图(type=person)**示例:
### 人物描述
**形象**:年龄段 + 风格
**穿搭**
- 上装:颜色+款式
- 下装:颜色+款式
- 配饰:...
**气质**:表情+姿势+整体感觉
**风景/场景图(type=scene)**示例:
### 场景名称
**类型**:自然风景/城市街景/动物/美食
**主体**:画面主要元素
**氛围**:整体感觉描述
要求:
- 内容真实具体,从实际图片分析得出
- 用 markdown 语法:**加粗**、列表、标题
- 控制在 100-200 字
- 不要编造图片中没有的信息
"""
# ── storyboard v3 追加的 system prompt 内容 ──────────────────────────
V3_STORYBOARD_APPEND = """
## 用户端展示格式
在输出分镜脚本的同时,在顶层输出一个 **copy_display_markdown** 字段(用 XML 标签 <copy_display_markdown> 包裹),用 markdown 格式写出完整文案展示。
格式示例:
# 标题/主题
## 整体概要
一句话描述视频内容
## 分镜预览
### 镜头1(0-3秒)
**景别**:近景俯拍,缓慢推镜
**画面**:场景描述
**台词**:口播文本
**动作**:人物动作描述
### 镜头2(3-9秒)
...
## 完整口播
完整口播文案文本
要求:
- 把所有分镜按时间顺序整理成易读的格式
- 用 markdown 语法组织,**加粗**标签、##二级标题、列表等
- 控制在 300-500 字
- 让用户一眼看懂视频会拍成什么样
"""
def upgrade() -> None:
bind = op.get_bind()
# ── 1. image_analysis v8 ──────────────────────────────────────────
# 停用所有 active image_analysis prompt
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = FALSE "
"WHERE prompt_type = 'image_analysis' AND is_active = TRUE"
)
)
# 读取 v7 的 prompt 内容作为基础
v7_row = bind.execute(
text(
"SELECT system_prompt, user_prompt_template, COALESCE(example_output, '') "
"FROM viral_video_prompt_templates "
"WHERE prompt_type = 'image_analysis' "
"ORDER BY version DESC LIMIT 1"
)
).fetchone()
if v7_row:
v7_system = v7_row[0] or ""
v8_system = v7_system + V8_SYSTEM_APPEND
v8_user = v7_row[1] or "{image_url}"
v8_example = v7_row[2] or ""
# 幂等:已有 v8 则更新,否则插入
existing_v8 = bind.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type = 'image_analysis' AND version = 8")
).fetchone()
if existing_v8:
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE, "
"system_prompt = :sys, user_prompt_template = :usr, "
"example_output = :ex, name = 'v8 用户端展示格式', "
"updated_at = NOW() "
"WHERE prompt_type = 'image_analysis' AND version = 8"
),
{"sys": v8_system, "usr": v8_user, "ex": v8_example},
)
else:
bind.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(prompt_type, version, name, system_prompt, user_prompt_template, "
"example_output, is_active, created_at, updated_at) "
"VALUES ('image_analysis', 8, 'v8 用户端展示格式', "
":sys, :usr, :ex, TRUE, NOW(), NOW())"
),
{"sys": v8_system, "usr": v8_user, "ex": v8_example},
)
# ── 2. storyboard v3 ─────────────────────────────────────────────
# 停用所有 active storyboard prompt
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = FALSE "
"WHERE prompt_type = 'storyboard' AND is_active = TRUE"
)
)
# 读取当前 storyboard prompt
sb_row = bind.execute(
text(
"SELECT system_prompt, user_prompt_template, COALESCE(example_output, '') "
"FROM viral_video_prompt_templates "
"WHERE prompt_type = 'storyboard' "
"ORDER BY version DESC LIMIT 1"
)
).fetchone()
if sb_row:
sb_system = sb_row[0] or ""
v3_system = sb_system + V3_STORYBOARD_APPEND
v3_user = sb_row[1] or ""
v3_example = sb_row[2] or ""
existing_v3 = bind.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type = 'storyboard' AND version = 3")
).fetchone()
if existing_v3:
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE, "
"system_prompt = :sys, user_prompt_template = :usr, "
"example_output = :ex, name = 'v3 用户端展示格式', "
"updated_at = NOW() "
"WHERE prompt_type = 'storyboard' AND version = 3"
),
{"sys": v3_system, "usr": v3_user, "ex": v3_example},
)
else:
bind.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(prompt_type, version, name, system_prompt, user_prompt_template, "
"example_output, is_active, created_at, updated_at) "
"VALUES ('storyboard', 3, 'v3 用户端展示格式', "
":sys, :usr, :ex, TRUE, NOW(), NOW())"
),
{"sys": v3_system, "usr": v3_user, "ex": v3_example},
)
def downgrade() -> None:
bind = op.get_bind()
# 删除 v8
bind.execute(
text("DELETE FROM viral_video_prompt_templates " "WHERE prompt_type = 'image_analysis' AND version = 8")
)
# 恢复 v7 active
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE, updated_at = NOW() "
"WHERE prompt_type = 'image_analysis' AND version = 7"
)
)
# 删除 v3
bind.execute(text("DELETE FROM viral_video_prompt_templates " "WHERE prompt_type = 'storyboard' AND version = 3"))
# 恢复 storyboard v2 active
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE, updated_at = NOW() "
"WHERE prompt_type = 'storyboard' AND version = 2"
)
)
+116
View File
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
"""image_analysis v8 + storyboard v3 叙述优先重写版(架构大简化)
Revision ID: 105_narration_first
Revises: 104_v8_display_markdown
Create Date: 2026-10-07
变更:
1. image_analysis v8:用「叙述优先」版整体替换 104 的 append 版——VLM 主交付物是
自然叙述 summary_markdown,结构化字段仅保留 type/name/brand/has_person,
顶层 products 改名 images;v8 active,其余 image_analysis 全部 deactivate。
2. storyboard v3:整体替换为风格重写版(口播口语化、画面有画面感、
copy_display_markdown 流畅叙述);v3 active,其余 storyboard deactivate。
3. intent_parsing 类型模板全部 deactivate(意图解析步骤已删除)。
模板内容直接取自 packages.application.viral_video.prompts.DEFAULT_TEMPLATES,
保证代码默认值与 DB seed 完全一致。
"""
from sqlalchemy import text
from alembic import op
from packages.application.viral_video.prompts import DEFAULT_TEMPLATES
revision = "105_narration_first"
down_revision = "104_v8_display_markdown"
branch_labels = None
depends_on = None
def _tpl(prompt_type: str, version: int) -> dict:
for t in DEFAULT_TEMPLATES:
if t["prompt_type"] == prompt_type and t["version"] == version:
return t
raise RuntimeError("default template missing: %s v%s" % (prompt_type, version))
def _upsert(bind, t: dict) -> None:
existing = bind.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type = :pt AND version = :ver"),
{"pt": t["prompt_type"], "ver": t["version"]},
).fetchone()
params = {
"pt": t["prompt_type"],
"ver": t["version"],
"name": t["name"],
"sys": t["system_prompt"],
"usr": t["user_prompt_template"],
"ex": t.get("example_output", "") or "",
}
if existing:
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET name = :name, "
"system_prompt = :sys, user_prompt_template = :usr, "
"example_output = :ex, is_active = TRUE, updated_at = NOW() "
"WHERE prompt_type = :pt AND version = :ver"
),
params,
)
else:
bind.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(prompt_type, version, name, system_prompt, user_prompt_template, "
"example_output, is_active, created_at, updated_at) "
"VALUES (:pt, :ver, :name, :sys, :usr, :ex, TRUE, NOW(), NOW())"
),
params,
)
def upgrade() -> None:
bind = op.get_bind()
# 1. image_analysis:停用全部后写入叙述优先 v8
bind.execute(
text("UPDATE viral_video_prompt_templates SET is_active = FALSE " "WHERE prompt_type = 'image_analysis'")
)
_upsert(bind, _tpl("image_analysis", 8))
# 2. storyboard:停用全部后写入重写版 v3
bind.execute(text("UPDATE viral_video_prompt_templates SET is_active = FALSE " "WHERE prompt_type = 'storyboard'"))
_upsert(bind, _tpl("storyboard", 3))
# 3. intent_parsing 已废弃:全部停用
bind.execute(
text("UPDATE viral_video_prompt_templates SET is_active = FALSE " "WHERE prompt_type = 'intent_parsing'")
)
# 4. review 模板确保 active
bind.execute(text("UPDATE viral_video_prompt_templates SET is_active = TRUE " "WHERE prompt_type = 'review'"))
def downgrade() -> None:
bind = op.get_bind()
# 恢复 104 的 v8/v3 无法重建(内容已替换),仅把版本 active 状态回退:
# 停用新版,尝试恢复 v7 / v2
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = FALSE "
"WHERE prompt_type IN ('image_analysis','storyboard') "
"AND version IN (8, 3)"
)
)
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE "
"WHERE prompt_type = 'image_analysis' AND version = 7"
)
)
bind.execute(
text(
"UPDATE viral_video_prompt_templates SET is_active = TRUE "
"WHERE prompt_type = 'storyboard' AND version = 2"
)
)
+48 -1
View File
@@ -44,6 +44,7 @@ from packages.application import (
GetGenerationTaskUseCase,
ListGeneratedVideosByTaskUseCase,
)
from packages.domain import feature_pricing_service
from packages.domain.smart_match import smart_select_assets
# #2035:文案关键词 → 素材分类 映射表(用于 smart_match category_match 维度)
@@ -163,7 +164,6 @@ def _infer_expected_categories(script_tags: set[str] | None) -> set[str] | None:
return matched or None
logger = logging.getLogger(__name__)
router = APIRouter()
@@ -700,6 +700,17 @@ def create_generation_task(
logger.info("画中画已下线,strategy_id %s → one_take", effective_strategy_id)
effective_strategy_id = "one_take"
# ── smart_edit 计费预扣(全局 points 开关 + 功能开关均开才扣) ──
# 首期固定价:dynamic_cost=0,price=(0+fixed_cost)×multiplier,price_cap 封顶。
# 预览任务不扣费;按任务条数扣费,任一任务预扣失败(余额不足)整体拒绝。
smart_edit_charge = 0.0
charged_task_count = 0
if not request.is_preview and feature_pricing_service.is_feature_enabled("smart_edit"):
unit_credits, _bd = feature_pricing_service.calculate_price("smart_edit", 0.0)
if unit_credits > 0:
smart_edit_charge = round(unit_credits * count, 2)
charged_task_count = count
# 批量生成(count>1):每个变体必须走与单视频完全相同的独立选片流程(#1743/#1749)。
# - 变体 0:clone 源 plan(不污染源 plan),变体 1..N-1 用 reselect_plan_for_variant
# 完整重跑选片(素材级去重:fresh 优先 → 受控复用 overlap≤20% → 短素材禁复用);
@@ -930,6 +941,42 @@ def create_generation_task(
)
# 变体序号写入 extra_meta(响应/排查时可辨识)
task.extra_meta["variant_index"] = task_index
# smart_edit 逐条预扣(首期固定价,credits_cost=prepaid,不做结算)
task_txn_id = ""
if charged_task_count > 0:
from packages.domain.points_service import PointsService
unit_credits = round(smart_edit_charge / count, 2)
res = PointsService().deduct_points(
user_id=user_id,
amount=unit_credits,
source="smart_edit",
db=db,
description="智能剪辑生成预扣",
ref_id=task.id,
)
if not res.get("success"):
# 余额不足:退还本次请求已扣积分后整体拒绝
already_charged = round(unit_credits * task_index, 2)
if already_charged > 0:
PointsService().refund_points(
user_id=user_id,
amount=already_charged,
source="smart_edit",
db=db,
ref_id=task.id,
description="智能剪辑批量提交失败退回",
)
raise HTTPException(
status_code=402,
detail=(f"积分不足:智能剪辑每条需 {unit_credits:.2f} 积分,当前余额 {res.get('balance', 0)}"),
)
task_txn_id = str(res.get("transaction_id") or "")
task.credits_prepaid = unit_credits
task.credits_cost = unit_credits
task.credits_transaction_id = task_txn_id
generation_task_repository.update(task)
try:
# 兜底关联编辑计划:前端未传 source_edit_plan_id 时,
# 通过 template_id + user_id 在 DB 层直接查找最新的 plan。
+15 -12
View File
@@ -145,19 +145,22 @@ def get_rules(
def get_packages(
current_user: AuthenticatedUser = Depends(get_current_user),
):
"""查询可购买的积分包列表。"""
packages = []
for code, pkg in POINTS_PACKAGES.items():
unit_price = f"¥{pkg['price_cents'] / 100 / pkg['points']:.3f}/积分"
packages.append(
PointsPackageItem(
code=code,
name=pkg["name"],
points=pkg["points"],
price_cents=pkg["price_cents"],
unit_price=unit_price,
)
"""查询可购买的积分包列表(读管理后台 credit_packages 表真实数据)。
仅返回 is_active=true;后台改价/启停后最多 30 秒生效。
"""
from packages.application.catalog.admin_catalog import get_points_packages
packages = [
PointsPackageItem(
code=row["code"],
name=row["name"],
points=row["points"],
price_cents=row["price_cents"],
unit_price=row["unit_price"],
)
for row in get_points_packages()
]
mt = _member_type(current_user)
discount = MEMBER_DISCOUNT.get(mt) if mt else None
return PointsPackagesResponse(packages=packages, user_discount=discount)
+4 -24
View File
@@ -86,33 +86,13 @@ async def get_current_subscription(
def list_membership_plans(
current_user: AuthenticatedUser = Depends(get_current_user),
) -> dict[str, list[dict[str, Any]]]:
"""查询所有会员档位(供前端会员购买页展示)。
"""查询可购买的会员套餐(读管理后台 plans 表真实数据)。
返回 points 积分体系下的会员档位(月卡/季卡/年卡),含价格、时长、积分折扣等信息。
仅返回 is_enabled=true 的套餐;后台启停/改价后最多 30 秒生效。
"""
from packages.domain.points_rules import MEMBER_DISCOUNT, MEMBERSHIP_PRICES
from packages.application.catalog.admin_catalog import get_membership_plans
plans: list[dict[str, Any]] = []
for plan_id, info in MEMBERSHIP_PRICES.items():
days = info["duration_days"]
monthly_cents = round(info["price_cents"] * 30 / days)
features: dict[str, Any] = {"max_resolution": "1080p"}
if plan_id == MembershipType.MONTHLY:
features.update({"free_clips_daily": 2})
elif plan_id == MembershipType.QUARTERLY:
features.update({"free_clips_daily": 5})
elif plan_id == MembershipType.YEARLY:
features.update({"free_clips_daily": "unlimited"})
plans.append({
"plan_id": plan_id,
"name": info["name"],
"price_cents": info["price_cents"],
"monthly_price_cents": monthly_cents,
"duration_days": days,
"points_discount": MEMBER_DISCOUNT.get(plan_id, 1.0),
"features": features,
})
return {"plans": plans}
return {"plans": get_membership_plans()}
@router.get("/billing-records", response_model=list[BillingRecord])
+30 -4
View File
@@ -146,6 +146,7 @@ def _to_response(job) -> ViralVideoJobResponse:
video_model=getattr(job, "video_model", "") or "",
intent_result=job.intent_result,
result_video_url=job.result_video_url,
pre_trusted_images=getattr(job, "pre_trusted_images", None) or None,
video_resolution=getattr(job, "video_resolution", "720p") or "720p",
credits_prepaid=float(getattr(job, "credits_prepaid", 0) or 0),
credits_cost=float(getattr(job, "credits_cost", 0) or 0),
@@ -279,11 +280,18 @@ def generate_copy(
raise HTTPException(status_code=404, detail="任务不存在")
if job.user_id != authenticated_user.user.id:
raise HTTPException(status_code=403, detail="无权操作此任务")
if job.status not in (ViralVideoStatus.IMAGE_ANALYZED, ViralVideoStatus.PENDING, ViralVideoStatus.FAILED):
# 允许首次进入(IMAGE_ANALYZED/PENDING)、失败重试(FAILED)、文案重新生成(COPY_GENERATED/COMPLETED)
if job.status not in (
ViralVideoStatus.IMAGE_ANALYZED,
ViralVideoStatus.PENDING,
ViralVideoStatus.FAILED,
ViralVideoStatus.COPY_GENERATED,
ViralVideoStatus.COMPLETED,
):
raise HTTPException(status_code=409, detail=f"任务当前状态 {job.status} 不能生成文案")
# 允许失败任务重试:重置
if job.status == ViralVideoStatus.FAILED:
# 失败重试 / 重新生成:retry_count 自增
if job.status in (ViralVideoStatus.FAILED, ViralVideoStatus.COPY_GENERATED, ViralVideoStatus.COMPLETED):
job.retry_count += 1
job.error_msg = ""
@@ -340,6 +348,9 @@ def confirm_copy(
raise HTTPException(status_code=403, detail="无权操作此任务")
if job.status != ViralVideoStatus.COPY_GENERATED:
raise HTTPException(status_code=409, detail=f"任务当前状态 {job.status} 不能确认文案(需 copy_generated)")
# #2218: 额外校验 copy_result 完整性,防止孤儿/脏数据进入渲染
if not isinstance(job.copy_result, dict) or not job.copy_result:
raise HTTPException(status_code=409, detail="文案数据缺失,请先点击「生成文案」")
# 积分预扣(已扣过/重试任务跳过)
from app.config import settings as _settings
@@ -879,13 +890,28 @@ async def viral_video_websocket(websocket: WebSocket, job_id: str) -> None:
job = job_repo.get(job_id)
if job is not None:
status_val = job.status.value if hasattr(job.status, "value") else str(job.status)
# #P0: 初始快照必须包含前端重连/刷新所需的业务字段,
# 结构对齐 worker 推送的 image_analyzed / copy_generated 事件。
data: dict = {"status": status_val}
ia = getattr(job, "image_analysis", None)
if isinstance(ia, dict) and ia:
data["image_analysis"] = ia
cr = _build_copy_result(job)
if isinstance(cr, dict) and cr:
data["copy_result"] = cr
gct = getattr(job, "generated_copy_text", "") or ""
if gct:
data["generated_copy_text"] = gct
sb = getattr(job, "storyboard", None) or []
if sb:
data["storyboard"] = sb
initial = {
"type": "viral_video:progress",
"job_id": job_id,
"stage": _stage_from_status(job),
"progress": _estimate_progress(job),
"message": _initial_message(job),
"data": {"status": status_val},
"data": data,
}
await websocket.send_json(initial)
# 已经终态 → 再发一条终态事件后立即关闭,避免占连接
+1
View File
@@ -222,6 +222,7 @@ class ViralVideoJobResponse(BaseModel):
video_model: str = ""
intent_result: dict | None = None
result_video_url: str = ""
pre_trusted_images: list[str] | None = None
video_resolution: str = "720p"
credits_prepaid: float = 0.0
credits_cost: float = 0.0
@@ -228,6 +228,8 @@ class GpuLipsyncService:
lipsync_job_id: str = "",
user_id: str = "",
project_id: str = "",
credits_prepaid: float = 0.0,
credits_transaction_id: str = "",
) -> GpuLipsyncTaskModel:
task_id = str(uuid.uuid4())
now = datetime.now(UTC)
@@ -240,6 +242,8 @@ class GpuLipsyncService:
audio_url=audio_url,
status="pending",
attempt=0,
credits_prepaid=float(credits_prepaid or 0.0),
credits_transaction_id=str(credits_transaction_id or ""),
created_at=now,
updated_at=now,
)
+222 -1
View File
@@ -38,6 +38,7 @@ from sqlalchemy.orm import Session
from packages.adapters.sqlalchemy_impl.models import LipsyncJobModel
from packages.application.cosyvoice_service import CosyVoiceError
from packages.config import get_api_settings
from packages.domain import feature_pricing_service
from packages.domain.sentence_timings import (
compute_sentence_timings,
probe_audio_duration,
@@ -222,7 +223,47 @@ class LipsyncService:
if timings:
job.sentence_timings = timings
# 4. 检查是否走 GPU 路径:开关打开 + 有可用 Worker
# 4. 检查是否走 Ditto(蚂蚁数字人,#2076):开关 + 配置完整
use_ditto = False
if self.settings.use_ditto_lipsync:
try:
from packages.application.ditto_service import get_ditto_client
ditto = get_ditto_client()
if ditto.is_configured:
use_ditto = True
logger.info("[lipsync] 优先走 Ditto 蚂蚁数字人: job_id=%s", job.id)
else:
logger.info(
"[lipsync] Ditto 开关已开但配置不完整(base_url=%s, template=%s),继续判断 GPU: job_id=%s",
bool(ditto.base_url),
bool(ditto.default_video_url),
job.id,
)
except Exception as exc:
logger.warning("[lipsync] Ditto 初始化失败,继续判断 GPU: job_id=%s err=%s", job.id, exc)
if use_ditto:
try:
# Ditto 使用预置人物模板视频,不用用户上传的 video_url;
# 但保留用户 video_url 以便失败回退到 GPU/MediaKit。
job.status = "processing"
job.mediakit_task_id = "ditto:submitted"
job.updated_at = datetime.now(UTC)
self.db.commit()
from app.tasks.lipsync_ditto import lipsync_ditto_process_async
lipsync_ditto_process_async.apply_async(args=(job.id, job.user_id))
logger.info("[lipsync] Ditto 任务已异步派发: job_id=%s", job.id)
return
except Exception as exc:
logger.warning("[lipsync] Ditto 派发失败,回退 GPU/MediaKit: job_id=%s err=%s", job.id, exc)
try:
self.db.rollback()
except Exception:
pass
# 5. 检查是否走 GPU 路径:开关打开 + 有可用 Worker
use_gpu = False
if self.settings.use_gpu_lipsync:
try:
@@ -368,6 +409,8 @@ class LipsyncService:
lipsync_job_id=job.id,
user_id=job.user_id,
project_id=job.project_id,
credits_prepaid=float(getattr(job, "credits_prepaid", 0) or 0),
credits_transaction_id=str(getattr(job, "credits_transaction_id", "") or ""),
)
logger.info(
"[lipsync] 已创建 GPU 任务(异步): job_id=%s gpu_task=%s",
@@ -415,6 +458,121 @@ class LipsyncService:
job.output_duration,
)
# ── lip_sync 计费辅助 ────────────────────────────────────────────────
@staticmethod
def _estimate_duration(
*,
audio_duration: Optional[float] = None,
sentence_timings: Optional[list] = None,
script_text: str = "",
) -> float:
"""预估音频/成片秒数。
优先级:audio_duration(预合成前端已 ffprobe)> timings 末句 end_time >
脚本字数 / 5 字每秒 > 默认 10 秒。
"""
if audio_duration and float(audio_duration) > 0:
return float(audio_duration)
if sentence_timings:
max_end = 0.0
for item in sentence_timings:
if isinstance(item, dict):
end = item.get("end_time") or item.get("end") or 0.0
else:
end = 0.0
try:
max_end = max(max_end, float(end))
except (TypeError, ValueError):
continue
if max_end > 0:
return max_end
text = (script_text or "").strip()
if text:
return max(1.0, len(text) / 5.0)
return 10.0
def _settle_lip_sync(self, job: LipsyncJobModel, actual_duration: float) -> None:
"""按实际时长结算(首期只退不补:final < prepaid 退差额,> 不补)。
幂等:credits_cost 已 > 0 说明结算过,直接跳过。
结算失败不阻塞业务(结果已产出),仅记录日志。
"""
try:
prepaid = float(getattr(job, "credits_prepaid", 0) or 0)
if prepaid <= 0:
return
if float(getattr(job, "credits_cost", 0) or 0) > 0:
return
feature_cfg = feature_pricing_service.get_feature_config("lip_sync")
unit_cost = float(feature_cfg.dynamic_unit_cost) if feature_cfg is not None else 0.0
duration = float(actual_duration or 0.0)
if duration <= 0:
duration = self._estimate_duration(
sentence_timings=job.sentence_timings,
script_text=job.script_text,
)
final_price, _bd = feature_pricing_service.calculate_price("lip_sync", duration * unit_cost)
final_price = round(float(final_price), 2)
job.credits_cost = final_price
if final_price < prepaid - 0.009:
refund = round(prepaid - final_price, 2)
from packages.domain.points_service import PointsService
res = PointsService().refund_points(
user_id=job.user_id,
amount=refund,
source="lip_sync",
db=self.db,
ref_id=str(job.credits_transaction_id or job.id),
description="对口型结算退费",
)
if not res.get("success"):
logger.warning(
"[lip_sync] 结算退费失败 job_id=%s refund=%.2f(不阻塞)",
job.id,
refund,
)
# final > prepaid:首期只退不补,不补扣
self.db.commit()
except Exception: # noqa: BLE001
logger.exception("[lip_sync] 结算异常 job_id=%s(不阻塞结果)", job.id)
try:
self.db.rollback()
except Exception: # noqa: BLE001
pass
def _refund_lip_sync(self, job: LipsyncJobModel) -> None:
"""任务失败/取消时全额退还预扣积分(credits_cost 已结算则退实际未消耗部分)。"""
try:
prepaid = float(getattr(job, "credits_prepaid", 0) or 0)
if prepaid <= 0:
return
txn_id = str(getattr(job, "credits_transaction_id", "") or "")
cost = float(getattr(job, "credits_cost", 0) or 0)
refund = round(prepaid - cost, 2) if cost > 0 else round(prepaid, 2)
if refund <= 0:
return
from packages.domain.points_service import PointsService
res = PointsService().refund_points(
user_id=job.user_id,
amount=refund,
source="lip_sync",
db=self.db,
ref_id=txn_id or job.id,
description="对口型失败/取消退款",
)
if res.get("success"):
job.credits_cost = prepaid # 标记已全额退回,防重复退
self.db.commit()
except Exception: # noqa: BLE001
logger.exception("[lip_sync] 退款异常 job_id=%s", job.id)
try:
self.db.rollback()
except Exception: # noqa: BLE001
pass
# ── 创建任务 ──────────────────────────────────────────────────────────
def create_job(
@@ -466,6 +624,35 @@ class LipsyncService:
if not isinstance(sentence_timings, list) or len(sentence_timings) == 0:
raise MediaKitError("预合成模式 sentence_timings 不能为空", code="InvalidInput")
# 0.5 lip_sync 计费预扣(全局 points 开关 + 功能开关均开才扣)
prepaid_credits = 0.0
prepaid_txn_id = ""
if feature_pricing_service.is_feature_enabled("lip_sync"):
est_duration = self._estimate_duration(
audio_duration=audio_duration,
sentence_timings=sentence_timings,
script_text=script_text,
)
feature_cfg = feature_pricing_service.get_feature_config("lip_sync")
unit_cost = float(feature_cfg.dynamic_unit_cost) if feature_cfg is not None else 0.0
dynamic_cost = est_duration * unit_cost
prepaid_credits, _bd = feature_pricing_service.calculate_price("lip_sync", dynamic_cost)
if prepaid_credits > 0:
from packages.domain.points_service import PointsService
res = PointsService().deduct_points(
user_id=user_id,
amount=prepaid_credits,
source="lip_sync",
db=self.db,
description="对口型生成预扣",
)
if not res.get("success"):
raise ValueError(
f"积分不足:本次对口型需 {prepaid_credits:.2f} 积分,当前余额 {res.get('balance', 0)}"
)
prepaid_txn_id = str(res.get("transaction_id") or "")
# 1. 创建数据库记录
job_id = str(uuid.uuid4())
job = LipsyncJobModel(
@@ -482,6 +669,8 @@ class LipsyncService:
emotion=emotion or "",
# 音频直传(含预合成)直接进入 pending(后续同步改为 submitted);TTS 模式进入 tts_processing
status="tts_processing" if is_tts_mode else "pending",
credits_prepaid=prepaid_credits,
credits_transaction_id=prepaid_txn_id,
)
self.db.add(job)
self.db.flush()
@@ -656,6 +845,30 @@ class LipsyncService:
if job.status in (STATUS_COMPLETED, "failed"):
return job
# Ditto 异步路径:mediakit_task_id 以 "ditto:" 开头,由 Celery 任务异步更新
# 不做 MediaKit 轮询,只检查是否卡住太久(>10 分钟)则标失败
if job.mediakit_task_id and job.mediakit_task_id.startswith("ditto:"):
if job.status in ("processing", "submitted"):
_now = datetime.now(UTC)
_upd = job.updated_at
if _upd is not None and _upd.tzinfo is None:
_upd = _upd.replace(tzinfo=UTC)
stale_minutes = 10
if _upd and (_now - _upd).total_seconds() > stale_minutes * 60:
logger.warning(
"Ditto 异步任务超时(>%d 分钟),标记失败: job_id=%s",
stale_minutes,
job_id,
)
job.status = "failed"
job.error_message = f"Ditto 处理超时(>{stale_minutes} 分钟)"
job.error_code = "DittoTimeout"
job.completed_at = _now
job.updated_at = _now
self.db.commit()
self._refund_lip_sync(job)
return job
# GPU 异步路径:mediakit_task_id 以 "gpu:" 开头,由 Celery 任务异步更新
# 不做 MediaKit 轮询,只检查是否卡住太久(>30 分钟)则标失败
if job.mediakit_task_id and job.mediakit_task_id.startswith("gpu:"):
@@ -677,6 +890,8 @@ class LipsyncService:
job.completed_at = _now
job.updated_at = _now
self.db.commit()
# lip_sync 超时全额退款
self._refund_lip_sync(job)
return job
# 未提交的任务不轮询
@@ -702,6 +917,8 @@ class LipsyncService:
job.completed_at = datetime.now(UTC)
job.updated_at = datetime.now(UTC)
self.db.commit()
# lip_sync 结算(只退不补)
self._settle_lip_sync(job, float(job.output_duration or 0.0))
# 异步转存自家 OSS
try:
from app.tasks.lipsync_tts import persist_output_video_task
@@ -719,6 +936,8 @@ class LipsyncService:
job.error_message = error.get("message", "任务执行失败")
job.error_code = error.get("code", "TaskFailed")
job.completed_at = datetime.now(UTC)
# lip_sync 失败全额退款(先退款再统一 commit)
self._refund_lip_sync(job)
else:
# 中间状态(running/processing/queued 等)同步到 DB,避免前端永远卡在 submitted
if isinstance(mk_status, str) and mk_status:
@@ -812,6 +1031,8 @@ class LipsyncService:
job.status = "cancelled"
job.updated_at = datetime.now(UTC)
self.db.commit()
# lip_sync 取消全额退款
self._refund_lip_sync(job)
self.db.refresh(job)
return job
+351
View File
@@ -0,0 +1,351 @@
"""Ditto 蚂蚁数字人口型异步任务 — #2076.
把 Ditto 同步 HTTP 调用(30-120s)从 API 请求移到 Celery 后台执行:
1. 加载 LipsyncJob
2. 调 DittoClient.generate_and_persist(video_url=默认模板, audio_url=job.audio_url, script=job.script_text)
3. 成功:标记 completed,写入 output_video_url(Ditto 输出自带音频,无需二次混流/超分)
4. 失败:回退 GPU MuseTalk → 再失败回退 MediaKit
注意:
- 保留 MuseTalk 代码不动;Ditto 优先,失败按原链路兜底
- Ditto 使用预置的人物模板视频(settings.ditto_default_video_url),不用用户上传的 video_url
- 不传 GFPGAN 超分,不需要 ffmpeg 音视频混流
"""
from __future__ import annotations
import logging
from datetime import UTC, datetime
from typing import TYPE_CHECKING, Optional
from celery import shared_task
from sqlalchemy.orm import Session
if TYPE_CHECKING:
from packages.adapters.sqlalchemy_impl.models import LipsyncJobModel
logger = logging.getLogger(__name__)
_DITTO_URL_TTL_SECONDS = 7 * 24 * 3600 # Ditto 结果 OSS URL 7 天有效
def _get_db_session() -> Session:
try:
from worker_app.db import SessionLocal # type: ignore
except ImportError:
from app.db import SessionLocal # type: ignore
return SessionLocal()
def _sign_media_url(url: str) -> str:
"""对自家 OSS URL 签 7 天预签名。"""
if not url:
return url
try:
from urllib.parse import urlparse
from packages.shared.storage import get_shared_storage_service
storage = get_shared_storage_service()
public_base = getattr(storage, "public_url", "")
if not isinstance(public_base, str) or not public_base:
return url
own_host = urlparse(public_base).netloc.lower()
host = urlparse(url).netloc.lower()
if not own_host or host != own_host:
return url
return storage.get_download_url(url, expires_seconds=_DITTO_URL_TTL_SECONDS)
except Exception:
return url
def _probe_video_duration(video_bytes: bytes) -> float:
"""用 ffprobe 探测视频时长(秒);失败返回 0。"""
try:
import os
import subprocess
import tempfile
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
tmp.write(video_bytes)
tmp_path = tmp.name
try:
out = subprocess.check_output(
[
"ffprobe",
"-v",
"error",
"-show_entries",
"format=duration",
"-of",
"default=noprint_wrappers=1:nokey=1",
tmp_path,
],
stderr=subprocess.STDOUT,
timeout=10,
)
return float(out.decode().strip() or 0)
finally:
os.unlink(tmp_path)
except Exception as exc:
logger.warning("[ditto_task] ffprobe 失败: %s", exc)
return 0.0
def _refund_lip_sync(db: Session, job: "LipsyncJobModel") -> None:
"""Ditto 失败/取消时全额退款(复用 lipsync_service 的退款逻辑)。"""
try:
from app.services.lipsync_service import LipsyncService
LipsyncService(db)._refund_lip_sync(job)
except Exception:
logger.exception("[ditto_task] lip_sync 退款异常 job_id=%s", job.id)
def _settle_lip_sync(db: Session, job: "LipsyncJobModel", duration: float) -> None:
"""Ditto 成功后按实际时长结算。"""
try:
from app.services.lipsync_service import LipsyncService
LipsyncService(db)._settle_lip_sync(job, duration)
except Exception:
logger.exception("[ditto_task] lip_sync 结算异常 job_id=%s(不阻塞)", job.id)
def _fallback_to_gpu_then_mediakit(db: Session, job: "LipsyncJobModel") -> None:
"""Ditto 失败后:优先回退 GPU MuseTalk,再回退 MediaKit 云端。
复用 lipsync_service 现有路径逻辑以保证兜底一致性。
"""
# 先尝试走 GPU MuseTalk(若可用)
try:
from app.services.gpu_lipsync_service import GpuLipsyncService
from app.tasks.lipsync_gpu import lipsync_gpu_process_async
gpu_svc = GpuLipsyncService(db)
if gpu_svc.has_available_worker():
logger.info("[ditto_task] 回退 GPU MuseTalk: job_id=%s", job.id)
# 复用 lipsync_service._submit_to_gpu_create 逻辑
from app.services.lipsync_service import LipsyncService
svc = LipsyncService(db)
storage = _shared_storage()
persisted_audio = None
try:
persisted_audio = svc._persist_external_audio_for_gpu(job=job, storage=storage)
except Exception as exc:
logger.warning("[ditto_task] GPU 外部音频转存失败: %s", exc)
audio_url_for_task = persisted_audio or job.audio_url
gpu_task = gpu_svc.create_task(
video_url=job.video_url,
audio_url=audio_url_for_task,
lipsync_job_id=job.id,
user_id=job.user_id,
)
if gpu_task is not None:
job.mediakit_task_id = f"gpu:{gpu_task.id}"
job.status = "processing"
job.updated_at = datetime.now(UTC)
db.commit()
lipsync_gpu_process_async.apply_async(args=(job.id, job.user_id, gpu_task.id))
return
db.rollback()
except Exception as exc:
logger.warning("[ditto_task] GPU MuseTalk 回退失败,转 MediaKit: %s", exc)
try:
db.rollback()
except Exception:
pass
# 最后兜底:MediaKit 云端
try:
from app.services.mediakit_client import get_mediakit_client
client = get_mediakit_client()
video_url = _sign_media_url(job.video_url)
signed_audio_url = _sign_media_url(job.audio_url)
result = client.submit_lipsync(
video_url=video_url,
audio_url=signed_audio_url,
enable_video_loop=job.enable_video_loop,
client_token=job.id,
)
job.mediakit_task_id = result["task_id"]
job.status = "submitted"
job.submitted_at = datetime.now(UTC)
job.updated_at = datetime.now(UTC)
db.commit()
logger.info("[ditto_task] 已回退 MediaKit: job_id=%s task_id=%s", job.id, result["task_id"])
except Exception as exc:
job.status = "failed"
job.error_message = f"Ditto/GPU/MediaKit 均失败: {exc}"
job.error_code = "AllBackendsFailed"
job.updated_at = datetime.now(UTC)
db.commit()
logger.error("[ditto_task] 所有兜底均失败: job_id=%s err=%s", job.id, exc)
def _shared_storage():
from packages.shared.storage import get_shared_storage_service
return get_shared_storage_service()
@shared_task(
name="lipsync_ditto_process_async",
bind=True,
max_retries=0,
acks_late=True,
time_limit=600,
soft_time_limit=540,
)
def lipsync_ditto_process_async(self, job_id: str, user_id: str) -> None:
"""异步调用 Ditto 生成口型视频。
Args:
job_id: LipsyncJob ID
user_id: 用户 ID
"""
from packages.application.ditto_emotion_service import get_ditto_emotion_service
from packages.application.ditto_service import DittoError, get_ditto_client
db: Session = _get_db_session()
job: Optional[LipsyncJobModel] = None
try:
from packages.adapters.sqlalchemy_impl.models import LipsyncJobModel
job = db.query(LipsyncJobModel).filter_by(id=job_id, user_id=user_id).first()
if job is None:
logger.error("[ditto_task] job 不存在: job_id=%s", job_id)
return
if job.status != "processing":
logger.warning(
"[ditto_task] job 状态异常(非 processing),跳过: job_id=%s status=%s",
job_id,
job.status,
)
return
audio_url = job.audio_url or ""
script = job.script_text or ""
if not audio_url:
raise DittoError("job.audio_url 为空,无法调用 Ditto", code="InvalidParam")
logger.info(
"[ditto_task] 开始 Ditto 生成: job_id=%s audio=%s script_len=%d",
job_id,
audio_url[:100],
len(script),
)
# ── LLM 情绪分析(#2076 后续):生成 emo_timeline ──
emo_timeline = ""
try:
emo_svc = get_ditto_emotion_service()
if emo_svc.enabled and script:
# 探测音频时长用于时间对齐
try:
from packages.domain.sentence_timings import probe_audio_duration
from packages.shared.url_security import safe_download_bytes
audio_bytes = safe_download_bytes(
audio_url,
allowed_mime_types=("audio/mpeg", "audio/wav", "audio/x-wav", "audio/mp3"),
timeout=30,
)
audio_duration = probe_audio_duration(audio_bytes)
except Exception as audio_exc:
logger.warning("[ditto_task] 音频时长探测失败,emo_timeline 降级空: %s", audio_exc)
audio_duration = 0.0
if audio_duration > 0:
sentence_timings = getattr(job, "sentence_timings", None)
emo_timeline = emo_svc.build_timeline(
text=script,
audio_duration=audio_duration,
sentence_timings=sentence_timings,
)
if emo_timeline:
logger.info("[ditto_task] 情绪时间线已生成: segments=%d", len(emo_timeline) // 50)
except Exception as emo_exc:
logger.warning("[ditto_task] 情绪分析异常(降级中性): %s", emo_exc)
emo_timeline = ""
client = get_ditto_client()
result = client.generate_and_persist(
job_id=job_id,
user_id=user_id,
audio_url=audio_url,
script=script,
emo_timeline=emo_timeline,
# video_url 不传则用默认模板
)
# Ditto 返回的 MP4 自带音频,签名 OSS URL(7天有效)后标记完成
job.output_video_url = _sign_media_url(result.video_url)
# 探测时长(用于计费)
duration = _probe_video_duration(result.video_bytes)
if duration <= 0:
# 兜底:按音频时长估算(1秒≈1秒)
try:
from packages.domain.sentence_timings import probe_audio_duration
from packages.shared.url_security import safe_download_bytes
audio_data = safe_download_bytes(
audio_url, allowed_mime_types=("audio/mpeg", "audio/wav", "audio/x-wav"), timeout=30
)
duration = probe_audio_duration(audio_data)
except Exception:
duration = 0.0
job.output_duration = duration
job.status = "completed"
job.completed_at = datetime.now(UTC)
job.updated_at = datetime.now(UTC)
db.commit()
logger.info(
"[ditto_task] Ditto 完成: job_id=%s url=%s duration=%.2fs rtf=%.2f frames=%d",
job_id,
result.video_url[:100],
duration,
result.rtf,
result.frames,
)
_settle_lip_sync(db, job, duration)
except DittoError as exc:
logger.error("[ditto_task] Ditto 失败,回退: job_id=%s code=%s err=%s", job_id, exc.code, exc)
if job is not None:
try:
db.rollback()
job = db.query(type(job)).filter_by(id=job_id).first() if hasattr(job, "id") else job
# 回退 GPU/MediaKit
_fallback_to_gpu_then_mediakit(db, job)
except Exception as fallback_exc:
logger.exception("[ditto_task] 回退也失败 job_id=%s err=%s", job_id, fallback_exc)
try:
if job:
job.status = "failed"
job.error_message = f"Ditto 失败且回退异常: {exc}; fallback: {fallback_exc}"
job.error_code = "FallbackError"
job.updated_at = datetime.now(UTC)
db.commit()
except Exception:
pass
except Exception as exc:
logger.exception("[ditto_task] 未预期异常: job_id=%s err=%s", job_id, exc)
if job is not None:
try:
db.rollback()
job = db.query(type(job)).filter_by(id=job_id).first()
_fallback_to_gpu_then_mediakit(db, job)
except Exception as fallback_exc:
logger.exception("[ditto_task] 回退也失败 job_id=%s err=%s", job_id, fallback_exc)
try:
if job:
job.status = "failed"
job.error_message = f"Ditto 异常: {exc}"
job.error_code = "DittoAsyncError"
job.updated_at = datetime.now(UTC)
db.commit()
except Exception:
pass
finally:
db.close()
+29
View File
@@ -104,6 +104,7 @@ def lipsync_gpu_process_async(self, job_id: str, user_id: str, gpu_task_id: str)
job.updated_at = datetime.now(UTC)
db.commit()
logger.info("[lipsync_gpu_async] GPU 任务已被用户取消: job_id=%s", job_id)
_refund_lip_sync(db, job)
return
if final_task.status != "done":
@@ -141,6 +142,7 @@ def lipsync_gpu_process_async(self, job_id: str, user_id: str, gpu_task_id: str)
job_id,
job.output_duration,
)
_settle_lip_sync(db, job, final_task)
except Exception as exc:
logger.exception("[lipsync_gpu_async] 异常: job_id=%s err=%s", job_id, exc)
try:
@@ -157,6 +159,33 @@ def lipsync_gpu_process_async(self, job_id: str, user_id: str, gpu_task_id: str)
db.close()
def _settle_lip_sync(db: Session, job: LipsyncJobModel, gpu_task) -> None:
"""GPU 成功后结算:同步 credits_cost 到 gpu 任务并按实际时长多退少不补。"""
try:
from app.services.lipsync_service import LipsyncService
# GPU 任务表先同步结算结果(标记用)
LipsyncService._settle_lip_sync(job, float(getattr(gpu_task, "result_duration", 0) or 0.0))
gpu_task.credits_cost = float(job.credits_cost or 0.0)
db.commit()
except Exception: # noqa: BLE001
logger.exception("[lipsync_gpu_async] lip_sync 结算异常 job_id=%s(不阻塞)", job.id)
try:
db.rollback()
except Exception: # noqa: BLE001
pass
def _refund_lip_sync(db: Session, job: LipsyncJobModel) -> None:
"""GPU 取消/失败路径全额退款。"""
try:
from app.services.lipsync_service import LipsyncService
LipsyncService(db)._refund_lip_sync(job)
except Exception: # noqa: BLE001
logger.exception("[lipsync_gpu_async] lip_sync 退款异常 job_id=%s", job.id)
def _fallback_to_mediakit(db: Session, job: LipsyncJobModel) -> None:
"""GPU 失败时回退到 MediaKit 云端渲染。"""
try:
+27 -1
View File
@@ -261,7 +261,33 @@ def tts_synthesize_and_submit(
"[lipsync_tts] 句子时间戳计算失败(不影响主流程): job_id=%s err=%s", job_id, _st_err, exc_info=True
)
# 3. 签名 URL 并提交到 MediaKit(复用模块内 _sign_media_url,避免对 LipsyncService 的耦合)
# 3. 优先走 Ditto(#2076):开关打开且配置完整时,派发 Ditto 异步任务,不再走 MediaKit
ditto_dispatched = False
try:
from packages.config import get_api_settings as _get_settings
_settings = _get_settings()
if _settings.use_ditto_lipsync and _settings.ditto_api_base_url and _settings.ditto_default_video_url:
from app.tasks.lipsync_ditto import lipsync_ditto_process_async
job.status = "processing"
job.mediakit_task_id = "ditto:tts-submitted"
job.updated_at = datetime.now(UTC)
db.commit()
lipsync_ditto_process_async.apply_async(args=(job_id, user_id))
logger.info("[lipsync_tts] TTS 完成,已派发 Ditto 任务: job_id=%s", job_id)
ditto_dispatched = True
except Exception as _ditto_err:
logger.warning("[lipsync_tts] Ditto 派发失败,回退 MediaKit: job_id=%s err=%s", job_id, _ditto_err)
try:
db.rollback()
except Exception:
pass
if ditto_dispatched:
return
# 4. 签名 URL 并提交到 MediaKit(复用模块内 _sign_media_url,避免对 LipsyncService 的耦合)
audio_url = _sign_media_url(job.audio_url)
video_url = _sign_media_url(job.video_url)
+12
View File
@@ -14,6 +14,7 @@
"axios": "^1.7.2",
"classnames": "^2.5.1",
"dayjs": "^1.11.23",
"marked": "^12.0.2",
"mp4box": "^2.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -4502,6 +4503,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/marked": {
"version": "12.0.2",
"resolved": "https://registry.npmmirror.com/marked/-/marked-12.0.2.tgz",
"integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+1
View File
@@ -25,6 +25,7 @@
"axios": "^1.7.2",
"classnames": "^2.5.1",
"dayjs": "^1.11.23",
"marked": "^12.0.2",
"mp4box": "^2.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+17 -19
View File
@@ -65,27 +65,23 @@ export function isAnalysisStage(stage: ViralVideoStage | undefined): boolean {
return isImageAnalysisStage(stage) || isCopyStage(stage)
}
/** 单张图片 VLM 识别出的商品信息 */
/** 单张图片 VLM 识别结果(v8 叙述优先,仅保留最少结构化字段) */
export interface ImageProductAnalysis {
/** store / product / person / scene */
type?: string
name?: string
category?: string
brand?: string
colors?: string[]
material_or_texture?: string
key_features?: string[]
visual_style?: string
scene?: string
target_audience_hint?: string
text_on_image?: string
/** 旧字段兼容 */
spec?: string
features?: string[] | string
label_text?: string
selling_points?: string
image_index?: number
has_person?: boolean
/** v8: 用户端展示用的叙述 markdown(由提示词控制排版) */
summary_markdown?: string
/** 标题行兼容字段 */
category?: string
}
export interface ImageAnalysisResult {
/** v8 字段 */
images?: ImageProductAnalysis[]
/** 老数据兼容 */
products?: ImageProductAnalysis[]
}
@@ -132,6 +128,8 @@ export interface CopyResult {
/** 向后兼容:= voiceover_script */
suggested_copy?: string
title?: string
/** v3 storyboard: 用户端展示用的 markdown 文案(由提示词控制排版) */
copy_display_markdown?: string
/** v1.5 旧字段兼容(老数据降级时可能出现) */
scenes?: Array<{ shot: string; narration: string; duration?: number }>
}
@@ -176,7 +174,7 @@ export interface ViralVideoJob {
fusion_level?: FusionLevel
voice_id?: string
voice_mode?: "global" | "per_video"
voice_source?: "preset" | "library" | "clone" | "upload"
voice_source?: "preset" | "library" | "clone" | "upload" | "my_voice"
bgm_preference?: string
intent_result?: IntentResult
intent_text?: string
@@ -212,7 +210,7 @@ export interface GenerateViralVideoRequest {
user_copy_text?: string
fusion_level?: FusionLevel
voice_id?: string
voice_source?: "preset" | "library" | "clone" | "upload"
voice_source?: "preset" | "library" | "clone" | "upload" | "my_voice"
bgm_preference?: string
industry?: string
target_customer?: string
@@ -244,7 +242,7 @@ export interface AnalyzeImagesRequest {
/** TTS 音色 ID(STEP1 已选音色时传) */
voice_id?: string
/** 音色来源:preset | library | clone | upload */
voice_source?: "preset" | "library" | "clone" | "upload"
voice_source?: "preset" | "library" | "clone" | "upload" | "my_voice"
/** Seedance 视频比例:9:16 | 16:9 | 1:1 */
video_ratio?: string
/** Seedance 模型 ID(空则使用服务端默认) */
@@ -273,7 +271,7 @@ export interface GenerateCopyRequest {
/** TTS 音色 ID(优先级高于 persona_id) */
voice_id?: string
/** 音色来源:preset | library | clone | upload */
voice_source?: "preset" | "library" | "clone" | "upload"
voice_source?: "preset" | "library" | "clone" | "upload" | "my_voice"
/** Seedance 视频比例(9:16/16:9/1:1 等) */
video_ratio?: string
/** Seedance 模型 ID(空则使用服务端默认) */
+2
View File
@@ -18,6 +18,8 @@ export interface VoiceClone {
language: string
gender: string
error_message: string | null
/** CosyVoice 实际使用的音色 ID(status=ready 时由后端填充,用于 TTS 调用) */
voice_id?: string | null
created_at: string
updated_at: string
}
+1
View File
@@ -18,6 +18,7 @@ export const toVoiceClone = (profile: VoiceCloneProfile): VoiceClone => ({
language: profile.language || "",
gender: profile.gender || "",
error_message: profile.error_message || null,
voice_id: profile.voice_id,
created_at: profile.created_at,
updated_at: profile.updated_at,
})
@@ -0,0 +1,182 @@
/* DurationWheelPicker —— 弹层式滚轮选择器(样式与表单一致) */
/* 触发按钮:外观复用 .vv-select 风格 */
.dw-trigger {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 36px;
padding: 0 12px;
background: #fff;
border: 1px solid #e0e0e8;
border-radius: 8px;
font-size: 13px;
color: #1f2937;
cursor: pointer;
box-sizing: border-box;
transition: all 0.15s;
user-select: none;
}
.dw-trigger:hover {
border-color: #c0c0d0;
}
.dw-trigger-open,
.dw-trigger:focus-within {
border-color: #7c3aed !important;
box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.12);
}
.dw-trigger-disabled {
opacity: 0.5;
pointer-events: none;
cursor: not-allowed;
}
.dw-trigger-val {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dw-trigger-placeholder {
color: #9ca3af;
}
.dw-trigger-arrow {
font-size: 10px;
color: #9ca3af;
margin-left: 8px;
transition: transform 0.2s;
}
.dw-trigger-arrow-up {
transform: rotate(180deg);
}
/* 弹层容器 */
.dw-popup {
padding: 8px;
min-width: 140px;
}
/* 滚轮 */
.dw-picker {
position: relative;
width: 100%;
overflow: hidden;
border-radius: 8px;
background: #fafafe;
border: 1px solid #e5e7eb;
}
.dw-picker-list {
margin: 0;
padding: 0;
list-style: none;
height: 100%;
overflow-y: scroll;
scroll-snap-type: y mandatory;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
.dw-picker-list::-webkit-scrollbar {
display: none;
}
.dw-picker-item {
display: flex;
align-items: baseline;
justify-content: center;
gap: 3px;
scroll-snap-align: center;
cursor: pointer;
font-size: 15px;
color: #9ca3af;
font-weight: 400;
transition:
color 0.15s,
transform 0.15s,
font-weight 0.15s;
}
.dw-picker-item-val {
font-variant-numeric: tabular-nums;
}
.dw-picker-item-unit {
font-size: 13px;
color: inherit;
}
.dw-picker-item-active {
color: #7c3aed;
font-weight: 600;
}
.dw-picker-item-active .dw-picker-item-val {
font-size: 18px;
}
.dw-picker-item-active .dw-picker-item-unit {
font-size: 14px;
}
/* 中心选中条 */
.dw-picker-mask {
position: absolute;
left: 6px;
right: 6px;
pointer-events: none;
background: #f5f0ff;
border-radius: 6px;
z-index: 1;
}
.dw-picker-mask::before,
.dw-picker-mask::after {
content: "";
position: absolute;
left: 0;
right: 0;
height: 1px;
background: #d8c4ff;
}
.dw-picker-mask::before {
top: 0;
}
.dw-picker-mask::after {
bottom: 0;
}
/* 上下渐变 */
.dw-picker-fade {
position: absolute;
left: 0;
right: 0;
height: 40%;
pointer-events: none;
z-index: 2;
}
.dw-picker-fade-top {
top: 0;
background: linear-gradient(to bottom, #fafafe 25%, rgba(250, 250, 254, 0));
}
.dw-picker-fade-bottom {
bottom: 0;
background: linear-gradient(to top, #fafafe 25%, rgba(250, 250, 254, 0));
}
/* 弹层按钮区 */
.dw-popup-actions {
display: flex;
gap: 8px;
justify-content: flex-end;
margin-top: 8px;
}
.dw-popup-actions .ant-btn {
border-radius: 6px;
}
.dw-popup-actions .ant-btn-primary {
background: #7c3aed;
}
.dw-popup-actions .ant-btn-primary:hover {
background: #6d28d9 !important;
}
/* 覆盖 antd Popover 默认内边距 */
.dw-popover .ant-popover-inner {
padding: 0 !important;
overflow: hidden;
}
.dw-popover .ant-popover-arrow {
display: none;
}
@@ -0,0 +1,180 @@
/**
* DurationWheelPicker —— 竖屏滚轮式时长选择器(弹层版)
*
* 设计:
* - 外观是和其他表单 Select 一致的输入框(白色底+1px灰边+紫色focus ring)
* - 点击输入框弹出 Popover,内部是滚轮 picker(原生 scroll-snap,零依赖)
* - 滚轮样式:白底容器,选中行 #7c3aed 紫字加粗+浅紫背景条
* - 支持触摸/鼠标滚轮/点击;松手吸附;底部"确认/取消"按钮
* - 默认范围 15–30 秒,步长 1 秒
*/
import React, { useEffect, useMemo, useRef, useState, useCallback } from "react"
import { Popover, Button } from "antd"
import { DownOutlined } from "@ant-design/icons"
import "./DurationWheelPicker.css"
export interface DurationWheelPickerProps {
value?: number
min?: number
max?: number
step?: number
unit?: string
onChange?: (value: number) => void
placeholder?: string
disabled?: boolean
/** 弹层宽度,默认 160px */
popupWidth?: number
/** 弹层内滚轮高度,默认 180px */
wheelHeight?: number
}
const ITEM_HEIGHT = 36
const DurationWheelPicker: React.FC<DurationWheelPickerProps> = ({
value = 20,
min = 15,
max = 30,
step = 1,
unit = "秒",
onChange,
placeholder = "请选择时长",
disabled = false,
popupWidth = 160,
wheelHeight = 180,
}) => {
const options = useMemo(() => {
const arr: number[] = []
for (let v = min; v <= max; v += step) arr.push(v)
return arr
}, [min, max, step])
const [open, setOpen] = useState(false)
// 弹层内暂存值,点确认才提交
const [draft, setDraft] = useState<number>(value)
const listRef = useRef<HTMLUListElement>(null)
const scrollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
useEffect(() => {
if (open) {
setDraft(value)
// 下一帧滚到当前值
requestAnimationFrame(() => scrollToValue(value, false))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open])
const scrollToValue = useCallback(
(v: number, smooth = true) => {
const list = listRef.current
if (!list) return
const idx = options.indexOf(v)
if (idx < 0) return
list.scrollTo({ top: idx * ITEM_HEIGHT, behavior: smooth ? "smooth" : "auto" })
},
[options],
)
const handleScroll = () => {
if (scrollTimerRef.current) clearTimeout(scrollTimerRef.current)
scrollTimerRef.current = setTimeout(() => {
const list = listRef.current
if (!list) return
const idx = Math.round(list.scrollTop / ITEM_HEIGHT)
const clamped = Math.max(0, Math.min(options.length - 1, idx))
const targetTop = clamped * ITEM_HEIGHT
if (Math.abs(list.scrollTop - targetTop) > 1) {
list.scrollTo({ top: targetTop, behavior: "smooth" })
}
setDraft(options[clamped])
}, 100)
}
const handleConfirm = () => {
onChange?.(draft)
setOpen(false)
}
const handleCancel = () => {
setOpen(false)
}
const handleItemClick = (v: number) => {
setDraft(v)
scrollToValue(v, true)
}
const maskTop = wheelHeight / 2 - ITEM_HEIGHT / 2
const wheel = (
<div className="dw-popup">
<div
className="dw-picker"
style={{ height: wheelHeight, width: popupWidth - 24 /* padding */ }}
>
<div className="dw-picker-mask" style={{ top: maskTop, height: ITEM_HEIGHT }} aria-hidden />
<div className="dw-picker-fade dw-picker-fade-top" aria-hidden />
<div className="dw-picker-fade dw-picker-fade-bottom" aria-hidden />
<ul
ref={listRef}
className="dw-picker-list"
onScroll={handleScroll}
style={{
paddingTop: wheelHeight / 2 - ITEM_HEIGHT / 2,
paddingBottom: wheelHeight / 2 - ITEM_HEIGHT / 2,
}}
>
{options.map((v) => {
const isActive = v === draft
return (
<li
key={v}
className={`dw-picker-item${isActive ? " dw-picker-item-active" : ""}`}
style={{ height: ITEM_HEIGHT, lineHeight: `${ITEM_HEIGHT}px` }}
onClick={() => handleItemClick(v)}
aria-selected={isActive}
role="option"
>
<span className="dw-picker-item-val">{v}</span>
<span className="dw-picker-item-unit">{unit}</span>
</li>
)
})}
</ul>
</div>
<div className="dw-popup-actions">
<Button size="small" onClick={handleCancel}>
取消
</Button>
<Button size="small" type="primary" onClick={handleConfirm}>
确认
</Button>
</div>
</div>
)
return (
<Popover
open={!disabled && open}
onOpenChange={(v) => setOpen(v)}
content={wheel}
trigger="click"
placement="bottomLeft"
overlayClassName="dw-popover"
overlayStyle={{ padding: 0 }}
overlayInnerStyle={{ padding: 0, borderRadius: 10 }}
destroyTooltipOnHide
>
<div
className={`dw-trigger${disabled ? " dw-trigger-disabled" : ""}${open ? " dw-trigger-open" : ""}`}
style={{ height: 36 }}
>
<span className={`dw-trigger-val${value != null ? "" : " dw-trigger-placeholder"}`}>
{value != null ? `${value}${unit}` : placeholder}
</span>
<DownOutlined className={`dw-trigger-arrow${open ? " dw-trigger-arrow-up" : ""}`} />
</div>
</Popover>
)
}
export default DurationWheelPicker
+1 -1
View File
@@ -10,4 +10,4 @@
* 功能流程不做积分预校验,直接走生成。
* - true:展示完整积分系统 UI。
*/
export const ENABLE_CREDIT_SYSTEM = false
export const ENABLE_CREDIT_SYSTEM = true
+22 -2
View File
@@ -80,6 +80,8 @@ const AiAvatarPage: React.FC = () => {
const [finalizeLoading, setFinalizeLoading] = useState(false)
/* ── 对口型轮询 ── */
/** 对口型轮询总时长上限(10分钟):超过后停止轮询并提示去历史记录查看 */
const LIPSYNC_POLL_MAX_MS = 10 * 60 * 1000
const lipsyncTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)
/* ── 渲染进度轮询 ── */
const renderTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)
@@ -270,7 +272,24 @@ const AiAvatarPage: React.FC = () => {
// 如果是预合成模式,后端会同步把状态置为 submitted(甚至可能已返回 running),
// 但仍需轮询等 completed
if (lipsyncTimerRef.current) clearInterval(lipsyncTimerRef.current)
// 轮询间隔 5 秒;单请求超时 5 分钟(见 api/aiAvatar.ts);总轮询上限 10 分钟
// 单次请求失败/超时不中断轮询,继续下一轮;超过总上限后停止并提示用户去历史记录查看
lipsyncTimerRef.current = setInterval(async () => {
// 总时长保护:超过 10 分钟停止轮询
if (Date.now() - lipsyncStartAtRef.current > LIPSYNC_POLL_MAX_MS) {
if (lipsyncTimerRef.current) {
clearInterval(lipsyncTimerRef.current)
lipsyncTimerRef.current = null
}
if (lipsyncTickRef.current) {
clearInterval(lipsyncTickRef.current)
lipsyncTickRef.current = null
}
setLipsyncStatus("failed")
setLipsyncErrorMessage("渲染时间较长,请稍后在历史记录中查看")
message.warning("对口型渲染时间较长,已停止自动刷新,请稍后在历史记录中查看")
return
}
try {
const updated = await getLipsyncJob(job.id)
state.setLipsyncJob(updated)
@@ -296,9 +315,10 @@ const AiAvatarPage: React.FC = () => {
setLipsyncErrorMessage(updated.error_message || "对口型生成失败")
}
} catch (err) {
console.error("[对口型] 轮询错误:", err)
// 单次轮询失败(含 timeout):不中断轮询,打印日志后等下一轮
console.warn("[对口型] 轮询请求失败,将继续下一轮:", err)
}
}, 3000)
}, 5000)
} catch (err) {
console.error("[对口型] 创建失败:", {
status: (err as { response?: { status?: number } })?.response?.status,
+6 -2
View File
@@ -72,7 +72,8 @@ export const previewTts = async (data: {
}
export const getLipsyncJob = async (id: string): Promise<LipsyncJob> => {
const response = await apiClient.get<LipsyncJob>(`/lipsync/jobs/${id}`, { timeout: 60000 })
// MuseTalk 渲染 8s 视频约 54s + 排队时间,给足 5 分钟超时避免单次轮询 AxiosError 中断
const response = await apiClient.get<LipsyncJob>(`/lipsync/jobs/${id}`, { timeout: 300_000 })
return response.data
}
@@ -91,7 +92,10 @@ export const submitRender = async (data: {
}
export const getRenderJob = async (jobId: string): Promise<RenderJob> => {
const response = await apiClient.get<RenderJob>(`/ai-avatar/render/${jobId}`, { timeout: 60000 })
// 渲染链路(对口型+B-roll+标题+合成+上传)耗时较长,给足 5 分钟超时
const response = await apiClient.get<RenderJob>(`/ai-avatar/render/${jobId}`, {
timeout: 300_000,
})
return response.data
}
@@ -1050,10 +1050,13 @@
flex-direction: column;
align-items: center;
justify-content: center;
height: 360px;
padding: 28px 16px;
gap: 10px;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 10px;
margin-top: 8px;
}
.vv-copy-loading .vv-spinner {
width: 28px;
@@ -1082,18 +1085,38 @@
/* ── Storyboard (linear doc style) ── */
.vv-storyboard {
padding: 6px 2px;
background: transparent;
border: none;
display: flex;
flex-direction: column;
height: 360px;
padding: 10px 12px;
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 10px;
margin-top: 8px;
overflow: hidden;
}
.vv-sb-doc {
flex: 1 1 auto;
display: flex;
flex-direction: column;
gap: 3px;
color: #1f2937;
font-size: 13px;
line-height: 1.55;
overflow-y: auto;
padding-right: 4px;
margin-right: -4px;
}
.vv-sb-doc::-webkit-scrollbar {
width: 6px;
}
.vv-sb-doc::-webkit-scrollbar-thumb {
background: #d8c4ff;
border-radius: 3px;
}
.vv-sb-doc::-webkit-scrollbar-track {
background: transparent;
}
.vv-sb-h {
margin: 6px 0 2px;
@@ -1383,12 +1406,14 @@
/* 口播稿 —— 复用 vv-sb-field 样式,无额外需求 */
.vv-sb-actions {
flex-shrink: 0;
display: flex;
align-items: center;
gap: 8px;
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #e5e7eb;
background: #fff;
}
.vv-sb-actions .vv-btn-ghost {
padding: 6px 14px;
@@ -1834,3 +1859,213 @@
color: #7c3aed;
font-weight: 500;
}
/* ── v1.6 我的音色(默认主路径) ── */
.vv-voice-section {
margin-top: 4px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background: #fff;
padding: 10px;
}
.vv-voice-section-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.vv-voice-section-title {
font-size: 13px;
font-weight: 600;
color: #1f2937;
display: inline-flex;
align-items: center;
gap: 6px;
}
.vv-voice-section-title .anticon {
color: #7c3aed;
}
.vv-link-btn-sm {
font-size: 12px;
padding: 2px 6px;
display: inline-flex;
align-items: center;
gap: 4px;
}
.vv-my-voice-list {
display: flex;
flex-direction: column;
gap: 4px;
max-height: 220px;
overflow-y: auto;
}
.vv-my-voice-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 10px;
border-radius: 6px;
cursor: pointer;
transition: background 0.15s;
}
.vv-my-voice-item:hover {
background: #f5f0ff;
}
.vv-my-voice-item.selected {
background: #f5f0ff;
}
.vv-my-voice-item.selected .vv-voice-radio {
border-color: #7c3aed;
background: #7c3aed;
box-shadow: inset 0 0 0 2px #fff;
}
.vv-voice-empty {
padding: 16px 12px;
text-align: center;
color: #9ca3af;
font-size: 12px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.vv-voice-empty-ic {
font-size: 28px;
color: #d1d5db;
}
.vv-voice-empty-text {
font-size: 12px;
}
.vv-voice-alt-row {
display: flex;
gap: 8px;
margin-top: 8px;
}
.vv-voice-alt-btn {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 10px;
background: #fafafe;
border: 1px solid #e5e7eb;
border-radius: 6px;
color: #6b7280;
font-size: 12px;
cursor: pointer;
transition: all 0.15s;
}
.vv-voice-alt-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
background: #f5f0ff;
}
.vv-voice-alt-btn.selected {
background: #f5f0ff;
border-color: #7c3aed;
color: #7c3aed;
}
.vv-voice-panel-actions {
display: flex;
gap: 12px;
margin-bottom: 6px;
padding-bottom: 6px;
border-bottom: 1px dashed #e5e7eb;
}
/* ─────────── markdown 渲染(提示词控制展示格式) ─────────── */
.vv-recog-md {
padding: 4px 0;
}
.vv-copy-preview {
margin-bottom: 14px;
padding: 12px 14px;
background: linear-gradient(180deg, #faf7ff 0%, #f6f2ff 100%);
border: 1px solid #ece4fb;
border-radius: 10px;
}
.vv-copy-preview-h {
margin: 0 0 8px;
border-bottom: none;
padding-bottom: 0;
}
.vv-md-body {
font-size: 13px;
line-height: 1.7;
color: #374151;
word-break: break-word;
}
.vv-md-body h1,
.vv-md-body h2,
.vv-md-body h3,
.vv-md-body h4 {
margin: 10px 0 6px;
font-weight: 600;
color: #1f2937;
line-height: 1.4;
}
.vv-md-body h1 {
font-size: 18px;
}
.vv-md-body h2 {
font-size: 16px;
}
.vv-md-body h3 {
font-size: 15px;
}
.vv-md-body h4 {
font-size: 14px;
}
.vv-md-body p {
margin: 6px 0;
}
.vv-md-body ul,
.vv-md-body ol {
margin: 6px 0;
padding-left: 20px;
}
.vv-md-body li {
margin: 3px 0;
}
.vv-md-body strong {
color: #111827;
font-weight: 600;
}
.vv-md-body blockquote {
margin: 8px 0;
padding: 4px 12px;
border-left: 3px solid #7c3aed;
background: rgba(124, 58, 237, 0.05);
color: #4b5563;
}
.vv-md-body code {
padding: 1px 5px;
background: #f3f4f6;
border-radius: 4px;
font-size: 12px;
color: #be185d;
}
.vv-md-body a {
color: #7c3aed;
text-decoration: none;
}
.vv-md-body a:hover {
text-decoration: underline;
}
.vv-md-body table {
border-collapse: collapse;
margin: 8px 0;
width: 100%;
}
.vv-md-body th,
.vv-md-body td {
border: 1px solid #e5e7eb;
padding: 6px 10px;
text-align: left;
}
.vv-md-body hr {
border: none;
border-top: 1px solid #e5e7eb;
margin: 12px 0;
}
+237 -111
View File
@@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useRef, useState } from "react"
import axios from "axios"
import { marked } from "marked"
import {
PlusOutlined,
CloseOutlined,
@@ -23,10 +24,13 @@ import {
CheckCircleFilled,
EditOutlined,
HistoryOutlined,
UserOutlined,
} from "@ant-design/icons"
import { Select, Input, message } from "antd"
import { uploadAssetDirect, getAssetLibraries, getAssetsByKind, type AssetItem } from "@/api/assets"
import { fetchPresetVoices } from "@/api/voices"
import { getVoiceClones, getVoiceClonePreview } from "@/api/voice-clone"
import type { VoiceClone } from "@/api/voice-clone"
import {
FUSION_LEVELS,
STYLE_STRENGTHS,
@@ -94,13 +98,15 @@ type RefVideo = {
} | null
type RefAudio = {
source: "preset" | "library" | "upload" | "clone"
source: "preset" | "library" | "upload" | "clone" | "my_voice"
id?: string
name: string
url?: string
/** 克隆音色的 CosyVoice voice_id(source=my_voice 时使用) */
ttsVoiceId?: string
} | null
type VoicePanel = "preset" | "upload" | "library" | "record" | "douyin" | null
type VoicePanel = "my_voices" | "preset" | "upload" | "library" | "record" | "douyin" | null
type TabTask = {
id: string
@@ -145,6 +151,16 @@ type TabTask = {
audioInst: HTMLAudioElement | null
}
/* ── marked 配置:禁用 mangle/headerIds,输出干净 HTML ── */
marked.setOptions({ gfm: true, breaks: false })
const renderMarkdown = (md: string): string => {
try {
return marked.parse(md ?? "", { async: false }) as string
} catch {
return (md ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;")
}
}
/* ─────────── 常量 ─────────── */
const LANGUAGES = ["中文(普通话)", "粤语", "英语", "日语", "韩语"]
@@ -213,12 +229,12 @@ const PURPOSES = [
"悬念短剧",
"情绪短片",
]
const DURATIONS = [15, 20, 30, 45, 60]
const RATIOS = [
{ v: "9:16", label: "9:16 竖屏(抖音/视频号)" },
{ v: "16:9", label: "16:9 横屏(B站/YouTube)" },
{ v: "1:1", label: "1:1 方形(小红书)" },
]
const DURATIONS = Array.from({ length: 16 }, (_, i) => 15 + i)
/** 兜底模型列表(接口未返回时使用,字段与 ViralVideoModel 对齐;后端返回后自动覆盖) */
const FALLBACK_VIDEO_MODELS: ViralVideoModel[] = [
{
@@ -291,6 +307,8 @@ interface Storyboard {
hard_constraints: string[]
negative_prompts: string[]
voiceover_script: string
/** v3: 用户端展示用 markdown 文案(由提示词控制排版) */
copy_display_markdown: string
}
/** 兼容旧 copy_result(final_copy/title/scenes)→ 新 Storyboard 结构 */
@@ -318,6 +336,7 @@ function copyResultToStoryboard(cr: CopyResult | null | undefined): Storyboard |
hard_constraints: Array.isArray(cr.hard_constraints) ? cr.hard_constraints : [],
negative_prompts: Array.isArray(cr.negative_prompts) ? cr.negative_prompts : [],
voiceover_script: cr.voiceover_script || cr.final_copy || cr.suggested_copy || "",
copy_display_markdown: cr.copy_display_markdown || "",
}
}
// 兜底:旧结构转简单分镜
@@ -353,6 +372,7 @@ function copyResultToStoryboard(cr: CopyResult | null | undefined): Storyboard |
hard_constraints: [],
negative_prompts: [],
voiceover_script: finalCopy,
copy_display_markdown: cr.copy_display_markdown || "",
}
}
@@ -407,6 +427,7 @@ const MOCK_STORYBOARD: Storyboard = {
negative_prompts: ["冷色调", "模糊", "变形", "水印文字", "卡通风格", "空无一人"],
voiceover_script:
"还在为餐桌选不到好桌子发愁?这张北美黑胡桃木餐桌,一家人坐下来吃饭刚刚好。全实木、无贴皮,纹理好看又耐刮。点小黄车,给家里添一张好桌子。",
copy_display_markdown: "",
}
const fmtSize = (bytes: number | undefined) => {
@@ -432,7 +453,7 @@ const emptyTask = (id: string, title: string): TabTask => ({
language: "中文(普通话)",
viralStructure: STRUCTURES[0],
marketingPurpose: "",
duration: 15,
duration: 20,
persona: "",
videoRatio: "9:16",
videoModel: "seedance-2.5",
@@ -485,6 +506,9 @@ const ViralVideoPage: React.FC = () => {
{ id: string; name: string; url: string; desc?: string }[]
>([])
const [presetVoices, setPresetVoices] = useState<PresetVoice[]>([])
/** 我的克隆音色(GET /voice-clones?status=ready) */
const [myVoices, setMyVoices] = useState<VoiceClone[]>([])
const [myVoicesLoading, setMyVoicesLoading] = useState(false)
const [voicePickerOpen, setVoicePickerOpen] = useState(false)
const [videoModels, setVideoModels] = useState<ViralVideoModel[]>(FALLBACK_VIDEO_MODELS)
const [assetPicker, setAssetPicker] = useState<{
@@ -514,8 +538,18 @@ const ViralVideoPage: React.FC = () => {
[activeId],
)
/* ── 加载音色 ── */
/* ── 加载音色(我的克隆音色 + 上传的配音素材 + 预设音色) ── */
const reloadMyVoices = useCallback(() => {
setMyVoicesLoading(true)
getVoiceClones({ status: "ready", limit: 50 })
.then((list) => {
setMyVoices(list.filter((v) => v.status === "ready"))
})
.catch(() => setMyVoices([]))
.finally(() => setMyVoicesLoading(false))
}, [])
useEffect(() => {
reloadMyVoices()
getAssetsByKind("voice", { limit: 50 })
.then((list) =>
setVoiceAssets(
@@ -523,7 +557,7 @@ const ViralVideoPage: React.FC = () => {
id: a.id,
name: a.name,
url: a.file_url || "",
desc: a.duration ? `${Math.round(a.duration)}s` : "我的音色",
desc: a.duration ? `${Math.round(a.duration)}s` : "配音文件",
})),
),
)
@@ -544,7 +578,7 @@ const ViralVideoPage: React.FC = () => {
// 接口失败兜底:弹窗内 MOCK_VOICES 会生效(voice_id 与后端 CosyVoice 一致)
setPresetVoices([])
})
}, [])
}, [reloadMyVoices])
/* ── 加载视频模型列表 ── */
useEffect(() => {
@@ -914,21 +948,36 @@ const ViralVideoPage: React.FC = () => {
[setTask, uploadFile],
)
const onCloneSuccess = (voice: { id?: string; name?: string }) => {
const onCloneSuccess = (
voice: VoiceClone | { id?: string; name?: string; voice_id?: string | null },
) => {
setCloneModalOpen(false)
// 克隆成功后刷新我的音色列表
reloadMyVoices()
const vid = "voice_id" in voice ? voice.voice_id : undefined
if (voice?.id) {
setTask({
refAudio: { source: "clone", id: voice.id, name: voice.name || "我录制的音色" },
refAudio: {
source: "my_voice",
id: voice.id,
name: voice.name || "我录制的音色",
ttsVoiceId: vid || undefined,
},
voicePanel: null,
})
getAssetsByKind("voice", { limit: 50 })
.then((list) =>
setVoiceAssets(
list.map((a) => ({ id: a.id, name: a.name, url: a.file_url || "", desc: "我的音色" })),
list.map((a) => ({
id: a.id,
name: a.name,
url: a.file_url || "",
desc: a.duration ? `${Math.round(a.duration)}s` : "配音文件",
})),
),
)
.catch(() => {})
message.success("录音已完成,已自动选中")
message.success("音色克隆完成,已自动选中")
}
}
@@ -1014,7 +1063,12 @@ const ViralVideoPage: React.FC = () => {
: undefined,
fusion_level: task.fusionLevel,
style_strength: task.refVideo?.ossUrl ? task.styleStrength : undefined,
voice_id: task.refAudio?.source === "preset" ? task.refAudio.id : undefined,
voice_id:
task.refAudio?.source === "preset"
? task.refAudio.id
: task.refAudio?.source === "my_voice"
? task.refAudio.ttsVoiceId || task.refAudio.id
: undefined,
voice_source: task.refAudio?.source || undefined,
video_ratio: task.videoRatio,
video_model: task.videoModel,
@@ -1058,7 +1112,12 @@ const ViralVideoPage: React.FC = () => {
style_strength: task.refVideo?.ossUrl ? task.styleStrength : undefined,
user_copy_text: task.storyboard?.voiceover_script || task.userCopy || undefined,
fusion_level: task.fusionLevel,
voice_id: task.refAudio?.id || undefined,
voice_id:
task.refAudio?.source === "preset"
? task.refAudio.id
: task.refAudio?.source === "my_voice"
? task.refAudio.ttsVoiceId || task.refAudio.id
: undefined,
voice_source: task.refAudio?.source,
industry: task.industry || undefined,
target_customer: task.targetCustomer || undefined,
@@ -1149,8 +1208,10 @@ const ViralVideoPage: React.FC = () => {
/* ── 识别描述汇览渲染 ── */
const renderRecognition = () => {
const products: ImageProductAnalysis[] =
(task.imageAnalysis?.products as ImageProductAnalysis[] | undefined) || []
const images: ImageProductAnalysis[] =
(task.imageAnalysis?.images as ImageProductAnalysis[] | undefined) ||
(task.imageAnalysis?.products as ImageProductAnalysis[] | undefined) ||
[]
if (task.uiStep === "step1_analyzing") {
return (
<div className="vv-recog">
@@ -1158,83 +1219,36 @@ const ViralVideoPage: React.FC = () => {
<LoadingOutlined style={{ color: "#7c3aed", marginRight: 6 }} />
识别描述汇览
</div>
<div className="vv-muted">AI 正在识别商品特征…</div>
<div className="vv-muted">AI 正在识别画面…</div>
</div>
)
}
if (products.length === 0) return null
const featureText = (f: string[] | string | undefined) => {
if (!f) return ""
if (Array.isArray(f)) return f.join(";")
return f
}
if (images.length === 0) return null
return (
<div className="vv-recog">
<div className="vv-recog-title">
<CheckCircleFilled style={{ color: "#10b981" }} />
识别描述汇览
</div>
{products.map((p, i) => (
<div key={i} className="vv-recog-item">
<div className="vv-recog-line">
<span className="vv-recog-k">图片{i + 1}:</span>
<span>
{p.name || "未识别"}
{p.spec && <span className="vv-recog-meta">({p.spec})</span>}
{p.brand && <span className="vv-recog-meta"> · {p.brand}</span>}
{p.category && <span className="vv-recog-meta"> · {p.category}</span>}
</span>
{images.map((p, i) => {
const meta = [p.name || "未识别", p.brand, p.category].filter(Boolean)
return (
<div key={i} className="vv-recog-item vv-recog-md">
<div className="vv-recog-line">
<span className="vv-recog-k">图片{i + 1}:</span>
<span>{meta.join(" · ")}</span>
</div>
{p.summary_markdown ? (
<div
className="vv-md-body"
dangerouslySetInnerHTML={{ __html: renderMarkdown(p.summary_markdown) }}
/>
) : (
<div className="vv-muted">(暂无叙述描述)</div>
)}
</div>
{featureText(p.key_features ?? p.features) && (
<div className="vv-recog-line">
<span className="vv-recog-k">核心特征:</span>
<span className="vv-recog-v">{featureText(p.key_features ?? p.features)}</span>
</div>
)}
{p.colors && p.colors.length > 0 && (
<div className="vv-recog-line">
<span className="vv-recog-k">主色调:</span>
<span className="vv-recog-v">{p.colors.join(" / ")}</span>
</div>
)}
{p.material_or_texture && (
<div className="vv-recog-line">
<span className="vv-recog-k">材质/纹理:</span>
<span className="vv-recog-v">{p.material_or_texture}</span>
</div>
)}
{p.visual_style && (
<div className="vv-recog-line">
<span className="vv-recog-k">视觉风格:</span>
<span className="vv-recog-v">{p.visual_style}</span>
</div>
)}
{p.scene && (
<div className="vv-recog-line">
<span className="vv-recog-k">场景:</span>
<span className="vv-recog-v">{p.scene}</span>
</div>
)}
{p.target_audience_hint && (
<div className="vv-recog-line">
<span className="vv-recog-k">目标人群:</span>
<span className="vv-recog-v">{p.target_audience_hint}</span>
</div>
)}
{(p.text_on_image || p.label_text) && (
<div className="vv-recog-line">
<span className="vv-recog-k">包装文字:</span>
<span className="vv-recog-v">{p.text_on_image || p.label_text}</span>
</div>
)}
{p.selling_points && (
<div className="vv-recog-line">
<span className="vv-recog-k">卖点:</span>
<span className="vv-recog-v">{p.selling_points}</span>
</div>
)}
</div>
))}
)
})}
</div>
)
}
@@ -1373,6 +1387,19 @@ const ViralVideoPage: React.FC = () => {
return (
<div className="vv-copy-box vv-storyboard">
<div className="vv-sb-doc">
{/* 文案预览(提示词控制排版,只读;编辑在下方分镜字段中进行) */}
{sb.copy_display_markdown && (
<div className="vv-copy-preview">
<h4 className="vv-sb-h vv-copy-preview-h">
<FileTextOutlined style={{ color: "#7c3aed", marginRight: 6 }} />
文案预览
</h4>
<div
className="vv-md-body"
dangerouslySetInnerHTML={{ __html: renderMarkdown(sb.copy_display_markdown) }}
/>
</div>
)}
{/* 视频总览 */}
<h4 className="vv-sb-h">视频总览</h4>
<p className="vv-sb-inline-row">
@@ -2033,43 +2060,119 @@ const ViralVideoPage: React.FC = () => {
)}
</div>
{/* 参考音频 2x2 */}
{/* 配音选择(默认"我的音色") */}
<div className="vv-subblock">
<div className="vv-subblock-head">
<span className="vv-subblock-title">参考音频</span>
<span className="vv-subblock-title">AI 配音</span>
<span className="vv-opt-tag">选填</span>
<span className="vv-subblock-hint">最大 10MB · 最长 30 秒</span>
<span className="vv-subblock-hint">
默认使用我的克隆音色,也可选择内置音色或上传配音
</span>
</div>
<div className="vv-audio-grid">
{/* 我的音色(主路径) */}
<div className="vv-voice-section">
<div className="vv-voice-section-head">
<span className="vv-voice-section-title">
<UserOutlined /> 我的音色
</span>
<button
className="vv-link-btn vv-link-btn-sm"
onClick={() => setCloneModalOpen(true)}
>
<PlusOutlined /> 录制新音色
</button>
</div>
{myVoicesLoading ? (
<div className="vv-muted vv-voice-empty">加载中…</div>
) : myVoices.length === 0 ? (
<div className="vv-voice-empty">
<AudioMutedOutlined className="vv-voice-empty-ic" />
<div className="vv-voice-empty-text">还没有克隆音色</div>
<button
className="vv-btn vv-btn-primary vv-btn-sm"
onClick={() => setCloneModalOpen(true)}
>
去录制一个
</button>
</div>
) : (
<div className="vv-my-voice-list">
{myVoices.map((v) => {
const selected =
task.refAudio?.source === "my_voice" && task.refAudio.id === v.id
const playing = task.playingVoiceId === `my-${v.id}`
return (
<div
key={v.id}
className={`vv-my-voice-item ${selected ? "selected" : ""}`}
onClick={() =>
setTask({
refAudio: {
source: "my_voice",
id: v.id,
name: v.name,
ttsVoiceId: v.voice_id || undefined,
},
voicePanel: null,
})
}
>
<div className="vv-voice-radio" />
<div className="vv-voice-info">
<div className="vv-voice-name">{v.name}</div>
<div className="vv-voice-desc">
AI 克隆声音
{v.gender
? ` · ${v.gender === "male" ? "男" : v.gender === "female" ? "女" : ""}`
: ""}
</div>
</div>
<button
className={`vv-voice-play ${playing ? "playing" : ""}`}
onClick={(e) => {
e.stopPropagation()
// 克隆音色试听:优先 sample_url,否则调用 preview 接口
if (v.sample_url) {
toggleVoice({ id: `my-${v.id}`, url: v.sample_url })
} else {
message.info("正在获取试听音频…")
getVoiceClonePreview(v.id)
.then((r) => {
if (r.audio_url)
toggleVoice({ id: `my-${v.id}`, url: r.audio_url })
})
.catch(() => message.error("试听获取失败"))
}
}}
>
{playing ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
</button>
</div>
)
})}
</div>
)}
</div>
{/* 次要选项:内置音色 / 上传配音 */}
<div className="vv-voice-alt-row">
<button
className={`vv-audio-cell ${task.refAudio?.source === "preset" ? "selected" : ""}`}
className={`vv-voice-alt-btn ${task.refAudio?.source === "preset" ? "selected" : ""}`}
onClick={() => setVoicePickerOpen(true)}
>
<FileTextOutlined className="vv-audio-ic" />
<span>选择内置音色</span>
<FileTextOutlined /> 内置音色
</button>
<button
className={`vv-audio-cell ${task.voicePanel === "upload" ? "active" : ""} ${task.refAudio?.source === "upload" ? "selected" : ""}`}
onClick={() => voiceInputRef.current?.click()}
className={`vv-voice-alt-btn ${task.refAudio?.source === "upload" || task.refAudio?.source === "library" ? "selected" : ""}`}
onClick={() =>
setTask({ voicePanel: task.voicePanel === "library" ? null : "library" })
}
>
<UploadOutlined className="vv-audio-ic" />
<span>本地上传</span>
</button>
<button
className={`vv-audio-cell ${task.voicePanel === "library" ? "active" : ""} ${task.refAudio?.source === "library" ? "selected" : ""}`}
onClick={() => setAssetPicker({ open: true, kind: "voice", multiple: false })}
>
<FolderOpenOutlined className="vv-audio-ic" />
<span>从素材库选择</span>
</button>
<button
className={`vv-audio-cell ${task.voicePanel === "record" ? "active" : ""} ${task.refAudio?.source === "clone" ? "selected" : ""}`}
onClick={() => setCloneModalOpen(true)}
>
<AudioMutedOutlined className="vv-audio-ic" />
<span>直接录音</span>
<FolderOpenOutlined /> 上传配音
</button>
</div>
<input
ref={voiceInputRef}
type="file"
@@ -2083,7 +2186,14 @@ const ViralVideoPage: React.FC = () => {
{task.refAudio && (
<div className="vv-selected-audio">
<SoundOutlined style={{ color: "#7c3aed", marginRight: 6 }} />
<span style={{ flex: 1 }}>已选:{task.refAudio.name}</span>
<span style={{ flex: 1 }}>
已选:
{task.refAudio.source === "my_voice"
? `我的音色 · ${task.refAudio.name}`
: task.refAudio.source === "preset"
? `内置 · ${task.refAudio.name}`
: task.refAudio.name}
</span>
<button className="vv-link-btn" onClick={() => setTask({ refAudio: null })}>
移除
</button>
@@ -2091,16 +2201,32 @@ const ViralVideoPage: React.FC = () => {
)}
{task.voicePanel === "library" && (
<div className="vv-voice-panel">
<div className="vv-voice-panel-actions">
<button
className="vv-link-btn vv-link-btn-sm"
onClick={() => voiceInputRef.current?.click()}
>
<UploadOutlined /> 本地上传音频文件
</button>
<button
className="vv-link-btn vv-link-btn-sm"
onClick={() =>
setAssetPicker({ open: true, kind: "voice", multiple: false })
}
>
<FolderOpenOutlined /> 从素材库选择
</button>
</div>
{voiceAssets.length === 0 ? (
<div className="vv-muted" style={{ padding: 12, textAlign: "center" }}>
暂无已上传的音频
暂无已上传的配音文件
</div>
) : (
<div className="vv-voice-list">
{voiceAssets.map((v) => (
<div
key={v.id}
className={`vv-voice-item ${task.refAudio?.id === v.id && task.refAudio.source === "library" ? "selected" : ""}`}
className={`vv-voice-item ${task.refAudio?.id === v.id && (task.refAudio.source === "library" || task.refAudio.source === "upload") ? "selected" : ""}`}
onClick={() =>
pickVoiceAsset({
id: v.id,
@@ -2289,7 +2415,7 @@ const ViralVideoPage: React.FC = () => {
options={PURPOSES.map((i) => ({ value: i, label: i }))}
/>
</div>
<div className="vv-form-row" style={{ gridColumn: "1 / -1" }}>
<div className="vv-form-row">
<label className="vv-label">文案视频时长</label>
<Select
className="vv-select"
+3
View File
@@ -53,6 +53,9 @@ celery_app.conf.imports = (
# #1998 GPU MuseTalk 异步推理:wait_for_result→签名 URL→回写 lipsync_jobs
# 必须在 Worker 侧注册,否则 apply_async 消息无人消费,job 永远卡在 processing
"app.tasks.lipsync_gpu",
# #2076 Ditto 蚂蚁数字人异步推理:同步 HTTP 调用 Ditto → MP4 流转存 OSS → 回写 lipsync_jobs
# 必须在 Worker 侧注册;失败回退 GPU MuseTalk → MediaKit
"app.tasks.lipsync_ditto",
)
# Celery Beat 定时任务调度
@@ -387,6 +387,41 @@ BATCH_RENDER_SIMILARITY_LIMIT = 0.20
"""批次内成片查重相似度阈值:超过则重选独立 plan 重渲一次(20%)。"""
def _refund_smart_edit_prepaid(task_id: str) -> None:
"""智能剪辑任务最终失败时退还预扣积分(幂等)。"""
session = SessionLocal()
try:
from packages.adapters.sqlalchemy_impl.generation_task_repository import (
SQLAlchemyGenerationTaskRepository,
)
from packages.domain.points_service import PointsService
repo = SQLAlchemyGenerationTaskRepository(session)
task = repo.get(task_id)
if not task:
return
prepaid = float(getattr(task, "credits_prepaid", 0) or 0)
if prepaid <= 0:
return
txn_id = getattr(task, "credits_transaction_id", "") or ""
res = PointsService().refund_points(
user_id=task.user_id,
amount=prepaid,
source="smart_edit",
db=session,
ref_id=task.id,
related_transaction_id=txn_id or None,
description="智能剪辑任务失败退回",
)
task.credits_cost = 0.0
task.credits_prepaid = 0.0
repo.update(task)
if not res.get("success"):
logger.warning("[task_id=%s] 失败退积分未成功: %s", task_id, res)
finally:
session.close()
def should_rerender_for_batch_dedup(*, batch_id: str, render_attempt: int, batch_similarity) -> bool:
"""批次内查重后判定是否需要重选 plan 重渲。
@@ -1167,6 +1202,10 @@ def generate_video(self, task_id: str) -> dict:
"mark_failed",
error_message="source_edit_plan_id is required. Please create a preview task first.",
)
try:
_refund_smart_edit_prepaid(task_id)
except Exception:
logger.warning("[task_id=%s] 失败退积分异常", task_id, exc_info=True)
return {
"status": "failed",
"task_id": task_id,
@@ -1205,6 +1244,7 @@ def generate_video(self, task_id: str) -> dict:
)
# ── 自动重试逻辑 ──────────────────────────────────────────────────
will_retry = False
try:
from packages.adapters.sqlalchemy_impl.generation_task_repository import (
SQLAlchemyGenerationTaskRepository,
@@ -1217,6 +1257,7 @@ def generate_video(self, task_id: str) -> dict:
if _task and _task.auto_retry_enabled and _task.auto_retry_max > 0:
current_retry = _task.retry_count or 0
if current_retry < _task.auto_retry_max:
will_retry = True
logger.info(
"[task_id=%s] 触发自动重试: 当前重试次数=%d, 最大重试次数=%d",
task_id,
@@ -1250,6 +1291,13 @@ def generate_video(self, task_id: str) -> dict:
exc_info=True,
)
# 最终失败(不再重试):退还 smart_edit 预扣积分
if not will_retry:
try:
_refund_smart_edit_prepaid(task_id)
except Exception:
logger.warning("[task_id=%s] 失败退积分异常", task_id, exc_info=True)
return {
"status": "failed",
"task_id": task_id,
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
"""V2 图片分析:火山OCR专用API + doubao-lite强约束JSON并行,单次pro VLM兜底。"""
from .fast_path import analyze_image_v2, analyze_images_v2 # noqa: F401
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
"""V2 prompt 解析:优先读后台 viral_video_prompt_templates(prompt_type='image_analysis'
且 is_active=true),30s TTL 热加载;DB 无有效记录/异常时,fallback 到 prompts.py 的
image_analysis v8 默认 system/user。
规则:
- DB 有 is_active=true 的 image_analysis 记录:system 原样用 DB.system_prompt
(自带完整输出格式,不追加任何硬编码 schema),user 用 DB.user_prompt_template
渲染(填入 image_url / ocr_text);
- DB 无记录/异常:system/user 用 prompts.py 里的 v8 默认模板。
"""
from __future__ import annotations
import logging
import threading
import time
logger = logging.getLogger(__name__)
def _default_template() -> dict:
# 延迟导入:避免模块加载时拉起整个 packages 依赖链(也便于旧 Python 收集测试)
from packages.application.viral_video.prompts import DEFAULT_TEMPLATES
for item in DEFAULT_TEMPLATES:
if item["prompt_type"] == "image_analysis":
return item
raise RuntimeError("image_analysis 默认模板缺失")
_cache_lock = threading.Lock()
_cache: dict[str, tuple[float, tuple[str, str]]] = {}
_CACHE_TTL = 30.0
def _load_db_template():
"""查 DB is_active=true 的 image_analysis 记录;不可达/无记录返回 None。"""
try:
from packages.application.viral_video.prompt_loader import _load_from_db
return _load_from_db("image_analysis")
except Exception as e: # noqa: BLE001
logger.warning("[vision.v2] 查询DB image_analysis prompt失败: %s", e)
return None
def _render_user(user_tpl: str, image_url: str, ocr_text: str) -> str:
try:
return user_tpl.format(image_url=image_url, ocr_text=ocr_text or "无")
except Exception: # noqa: BLE001
return user_tpl
def _resolve(kind: str, image_url: str = "", ocr_text: str = "") -> tuple[str, str]:
now = time.time()
cache_key = f"prompt_{kind}"
with _cache_lock:
hit = _cache.get(cache_key)
if hit and now - hit[0] < _CACHE_TTL:
sys_prompt, usr_prompt = hit[1]
return sys_prompt, _render_user(usr_prompt, image_url, ocr_text)
default = _default_template()
sys_prompt = default["system_prompt"]
usr_prompt = default["user_prompt_template"]
tpl = _load_db_template()
if tpl is not None:
db_sys = (getattr(tpl, "system_prompt", "") or "").strip()
if db_sys:
sys_prompt = db_sys
db_usr = getattr(tpl, "user_prompt_template", "") or usr_prompt
usr_prompt = db_usr or usr_prompt
logger.info(
"[vision.v2] 使用DB image_analysis prompt version=%s",
getattr(tpl, "version", "?"),
)
with _cache_lock:
_cache[cache_key] = (now, (sys_prompt, usr_prompt))
return sys_prompt, _render_user(usr_prompt, image_url, ocr_text)
def resolve_fast_prompt(image_url: str = "", ocr_text: str = "") -> tuple[str, str]:
return _resolve("fast", image_url, ocr_text)
def resolve_pro_prompt(image_url: str = "", ocr_text: str = "") -> tuple[str, str]:
return _resolve("pro", image_url, ocr_text)
def invalidate_cache() -> None:
with _cache_lock:
_cache.clear()
@@ -0,0 +1,106 @@
"""V2 结果组装(v8 叙述优先,大幅精简)。
设计原则:VLM 直接输出最终给用户看的 summary_markdown,assembler 只负责
- 解析 fast JSON(兼容顶层 {"images":[...]} 与 {"products":[...]} 两种键);
- 补齐 5 个必备字段(type/name/brand/has_person/summary_markdown);
- summary_markdown 缺失(异常)时才拼一句最基础的兜底文字。
正常情况下不改写、不“润色”VLM 输出,不做 brand 多级兜底,不处理任何
colors/material/key_features 等细分字段。
"""
from __future__ import annotations
import logging
from typing import Any
logger = logging.getLogger(__name__)
_VALID_TYPES = ("store", "product", "person", "scene")
def _coerce_bool(value: Any) -> bool:
if isinstance(value, bool):
return value
if isinstance(value, (int, float)):
return value != 0
if isinstance(value, str):
return value.strip().lower() in ("true", "1", "yes", "是")
return False
def _basic_markdown(image: dict[str, Any]) -> str:
"""异常兜底:VLM 没给 summary_markdown 时只拼一句基础文字。"""
name = (image.get("name") or "").strip() or "未识别"
brand = (image.get("brand") or "").strip()
typ = image.get("type") or "scene"
label = f"{brand}{name}" if brand and brand not in name else (brand or name)
if typ == "store":
return f"这是{label}的门店场景,画面细节识别不完整。"
if typ == "person":
return f"画面中的人物与{label}相关,细节识别不完整。"
if typ == "product":
return f"这是{label}的商品图片,具体外观细节识别不完整。"
return f"画面内容为{label},细节识别不完整。"
def _normalize_image(raw: Any, idx: int) -> dict[str, Any]:
"""把一条 VLM 输出归一化为 5 字段 dict。"""
if not isinstance(raw, dict):
raw = {}
typ = str(raw.get("type") or "").strip().lower()
if typ not in _VALID_TYPES:
typ = "scene"
name = str(raw.get("name") or "").strip() or "未识别"
brand = str(raw.get("brand") or "").strip()
has_person = _coerce_bool(raw.get("has_person"))
if typ == "person" and not has_person:
# type=person 通常意味着主体是人,保持一致(仅异常补全)
has_person = True
summary = raw.get("summary_markdown")
summary = summary.strip() if isinstance(summary, str) else ""
image: dict[str, Any] = {
"type": typ,
"name": name,
"brand": brand,
"has_person": has_person,
"summary_markdown": summary,
}
if not summary:
image["summary_markdown"] = _basic_markdown(image)
image["_source"] = "summary_missing"
logger.info("[assembler] 图片 #%s 缺少 summary_markdown,使用基础兜底", idx)
return image
def _extract_items(fast_json: Any) -> list[Any]:
"""从 fast JSON 中取出图片条目:优先 images,兼容 products。"""
if not isinstance(fast_json, dict):
return []
items = fast_json.get("images")
if not isinstance(items, list):
items = fast_json.get("products")
return items if isinstance(items, list) else []
def assemble_result(idx: int, fast_json: Any, ocr_texts: list[str] | None = None) -> dict[str, Any]:
"""组装单张图片分析结果。
每次调用对应一张图片;fast_json 形如 {"images": [{...}]}(v8)。
返回单条 image dict(5 字段,必要时带 _source)。
"""
items = _extract_items(fast_json)
if items:
image = _normalize_image(items[0], idx)
else:
# 极端异常:fast 无任何可用条目,OCR 文字可作为名称线索
ocr_hint = ""
if ocr_texts:
ocr_hint = "、".join(t for t in ocr_texts if t)[:40]
image = _normalize_image({"name": ocr_hint or "未识别", "summary_markdown": ""}, idx)
image["_source"] = "empty_fast_json"
return image
@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
"""V2 图片分析主路径(v8 叙述优先):每图并行 OCR(火山 MediaKit,未配置自动跳过)
+ fast VLM 强约束 JSON;失败时单次 pro VLM 兜底。
架构:
- 单图 2 路并行(OCR + fast VLM),外层 N 图全并发(workers=8);
- 兜底单次 pro VLM,无竞速/复杂重试;
- 输出统一为 5 字段 image dict(type/name/brand/has_person/summary_markdown)。
"""
from __future__ import annotations
import logging
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any
from . import assembler, ocr_volc, vlm_fallback, vlm_fast_json
logger = logging.getLogger(__name__)
_IMG_WORKERS = int(os.environ.get("VISION_V2_IMG_WORKERS", "8"))
_FAST_TIMEOUT = float(os.environ.get("VISION_V2_FAST_TIMEOUT", "20"))
_FAST_JSON_TIMEOUT = float(os.environ.get("VISION_V2_FAST_JSON_TIMEOUT", "20"))
_OCR_TIMEOUT = float(os.environ.get("VISION_V2_OCR_TIMEOUT", "6"))
_PRO_TIMEOUT = float(os.environ.get("VISION_V2_PRO_TIMEOUT", "45"))
def _is_usable(r: dict[str, Any] | None) -> bool:
if not isinstance(r, dict):
return False
return bool((r.get("summary_markdown") or "").strip())
def _basic_failure(ocr_result: list[str], fast_elapsed: float, source: str) -> dict[str, Any]:
image = assembler.assemble_result(-1, {}, ocr_result)
image["_source"] = source
image["_fast_elapsed"] = round(fast_elapsed, 2)
return image
def analyze_image_v2(idx: int, img_url: str) -> dict[str, Any]:
t0 = time.time()
fj_result: dict[str, Any] | None = None
ocr_result: list[str] = []
pool = ThreadPoolExecutor(max_workers=2)
f_fj = pool.submit(vlm_fast_json.call_fast_json, img_url, timeout=_FAST_JSON_TIMEOUT)
f_ocr = pool.submit(ocr_volc.call_ocr, img_url, timeout=_OCR_TIMEOUT)
try:
for fut in as_completed([f_fj, f_ocr], timeout=_FAST_TIMEOUT):
try:
res = fut.result(timeout=1)
except Exception as e: # noqa: BLE001
logger.warning("[vision.v2] 图片 #%d 子任务异常: %s", idx, e)
continue
if fut is f_fj and isinstance(res, dict):
fj_result = res
elif fut is f_ocr and isinstance(res, list):
ocr_result = res
except TimeoutError:
for f in (f_fj, f_ocr):
if not f.done():
f.cancel()
logger.warning("[vision.v2] 图片 #%d fast路径超时(%.0fs),走pro兜底", idx, _FAST_TIMEOUT)
finally:
fast_elapsed = time.time() - t0
pool.shutdown(wait=False)
if fj_result:
assembled = assembler.assemble_result(idx, fj_result, ocr_result)
if _is_usable(assembled):
assembled["_fast_elapsed"] = round(fast_elapsed, 2)
logger.info("[vision.v2] 图片 #%d fast命中 elapsed=%.2fs", idx, fast_elapsed)
return assembled
pro_result = vlm_fallback.call_pro_vlm(img_url, idx, ocr_hint=ocr_result, timeout=_PRO_TIMEOUT)
if _is_usable(pro_result):
pro_result["_fallback_used"] = True
pro_result["_fast_elapsed"] = round(fast_elapsed, 2)
logger.info("[vision.v2] 图片 #%d pro兜底命中 total=%.2fs", idx, time.time() - t0)
return pro_result
logger.warning("[vision.v2] 图片 #%d 全路径失败 elapsed=%.2fs", idx, time.time() - t0)
return _basic_failure(ocr_result, fast_elapsed, "v2_all_failed")
def analyze_images_v2(img_urls: list[str]) -> list[dict[str, Any]]:
if not img_urls:
return []
workers = min(_IMG_WORKERS, len(img_urls), 16)
results: list[dict[str, Any] | None] = [None] * len(img_urls)
logger.info(
"[vision.v2] 开始图片分析 n=%d workers=%d fast_timeout=%.0fs pro_timeout=%.0fs",
len(img_urls),
workers,
_FAST_TIMEOUT,
_PRO_TIMEOUT,
)
t0 = time.time()
with ThreadPoolExecutor(max_workers=workers) as pool:
future_to_idx = {pool.submit(analyze_image_v2, idx, url): idx for idx, url in enumerate(img_urls)}
for fut in as_completed(future_to_idx):
idx = future_to_idx[fut]
try:
results[idx] = fut.result()
except Exception as e: # noqa: BLE001
logger.warning("[vision.v2] 图片 #%d future异常: %s", idx, e, exc_info=True)
results[idx] = assembler.assemble_result(idx, {}, [])
results[idx]["_source"] = "v2_future_exception" # type: ignore[index]
elapsed = time.time() - t0
succ = sum(1 for r in results if _is_usable(r))
fb = sum(1 for r in results if r and r.get("_fallback_used"))
logger.info(
"[vision.v2] 完成 n=%d usable=%d pro_fallback=%d elapsed=%.2fs",
len(img_urls),
succ,
fb,
elapsed,
)
return [r for r in results if r is not None] # type: ignore[misc]
@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
"""VLM 返回文本的稳健 JSON 提取工具。
背景:复杂门店图 VLM 输出经常被 max_tokens 截断(finish_reason=length),
json.loads 失败后整个结果被丢弃,导致"未识别"。本工具提供:
1. markdown 代码块剥离(含只开不闭的截断场景)
2. 最外层 { } 切片
3. 非法控制字符清理
4. 直接 json.loads
5. 截断 JSON 括号/引号栈补全修复
6. 尾部逐字符截断重试(去除最后一个不完整 token 后修复)
成功返回 dict;截断修复产物带 _partial=True 标记;彻底失败返回 None。
"""
from __future__ import annotations
import json
import logging
import re
logger = logging.getLogger(__name__)
_CODE_FENCE_RE = re.compile(r"^```(?:json)?\s*\n?(.*?)\n?```\s*$", re.DOTALL)
def _strip_code_fence(s: str) -> str:
s = s.strip()
m = _CODE_FENCE_RE.match(s)
if m:
return m.group(1).strip()
# 兼容开头 ```json 但结尾无 ```(截断场景)
if s.startswith("```"):
lines = s.split("\n")
if lines and lines[0].startswith("```"):
lines = lines[1:]
s = "\n".join(lines).strip()
return s
def _repair_truncated_json(text: str) -> str:
"""尝试补全被截断的JSON:维护 bracket/quote 栈,在末尾补闭合符。"""
stack: list[str] = []
in_string = False
escape = False
for ch in text:
if escape:
escape = False
continue
if ch == "\\" and in_string:
escape = True
continue
if ch == '"':
in_string = not in_string
continue
if in_string:
continue
if ch in "{[":
stack.append(ch)
elif ch == "}":
if stack and stack[-1] == "{":
stack.pop()
elif ch == "]":
if stack and stack[-1] == "[":
stack.pop()
repair = ""
if in_string:
repair += '"'
for opener in reversed(stack):
repair += "}" if opener == "{" else "]"
if repair:
logger.info(
"[json_utils] 截断JSON修复: 补全%d个闭合符 in_string=%s",
len(repair),
in_string,
)
return text + repair
def _clean_invalid_chars(text: str) -> str:
"""清理JSON中非法的控制字符(tab/newline 之外的 0x00-0x1f 段)。"""
return re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f]", "", text)
def extract_json_object(text: str) -> dict | None:
"""从VLM返回文本中稳健提取JSON对象。
返回 dict 或 None。成功的 dict 可能带 _partial=True 标记,
表示原始文本被截断、经括号补全后得到的产物。
"""
if not text or not isinstance(text, str):
return None
# 1. 剥离 markdown
text = _strip_code_fence(text)
# 2. 找最外层 { }
lpos = text.find("{")
if lpos < 0:
return None
rpos = text.rfind("}")
if rpos > lpos:
text = text[lpos : rpos + 1]
else:
# 截断场景:无任何闭合 },取到末尾交给修复器
text = text[lpos:]
# 3. 清理非法控制字符
text = _clean_invalid_chars(text)
# 4. 直接 loads
try:
obj = json.loads(text)
return obj if isinstance(obj, dict) else None
except json.JSONDecodeError:
pass
# 5. 尝试截断修复
repaired = _repair_truncated_json(text)
try:
obj = json.loads(repaired)
if isinstance(obj, dict):
obj["_partial"] = True
return obj
except json.JSONDecodeError:
pass
# 6. 尾部逐字符截断重试(去除最后一个不完整 token)
for _ in range(50):
last_comma = repaired.rfind(",")
last_brace = max(repaired.rfind("}"), repaired.rfind("]"))
cut = max(last_comma, last_brace)
if cut < 10:
break
repaired = repaired[: cut + 1]
repaired = _repair_truncated_json(repaired)
try:
obj = json.loads(repaired)
if isinstance(obj, dict):
obj["_partial"] = True
return obj
except json.JSONDecodeError:
continue
return None
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""火山引擎 AI MediaKit OCR(同步)调用封装。
接口:POST {mediakit_base_url}/tools-sync/ocr
鉴权:Bearer {mediakit_api_key}
请求体:{"image_url": "<公网可访问URL>"} (部分版本也支持 image_base64)
响应:{"code":0,"data":{"texts":[{"text":"...","bbox":[x,y,w,h],...},...],...}}
目标:识别商品包装/Logo/水印上的文字,作为 fast_json VLM 的补充。
返回值:识别到的文本字符串列表(失败返回 [])。
"""
from __future__ import annotations
import logging
import time
from typing import Any
logger = logging.getLogger(__name__)
DEFAULT_TIMEOUT = 8 # OCR 秒级返回,8s 绰绰有余
def call_ocr(img_url: str, *, timeout: int = DEFAULT_TIMEOUT) -> list[str]:
"""调用 MediaKit 同步 OCR,返回去重后的纯文本列表。
不做重试(外层降级逻辑负责)。失败/未配置返回空列表,不抛异常。
"""
t0 = time.time()
try:
import httpx
from packages.shared.mediakit_client import get_mediakit_client
client = get_mediakit_client()
if not client.is_available:
logger.info("[vision.v2] mediakit 未配置,跳过 OCR")
return []
url = f"{client.base_url}/tools-sync/ocr"
headers = {
"Authorization": f"Bearer {client.api_key}",
"Content-Type": "application/json",
}
payload: dict[str, Any] = {"image_url": img_url}
# 部分文档版本用 image_base64,但公网 URL 场景下 image_url 最简
resp = httpx.post(url, headers=headers, json=payload, timeout=timeout)
elapsed = time.time() - t0
if resp.status_code != 200:
logger.warning(
"[vision.v2] OCR HTTP %d elapsed=%.1fs body=%s",
resp.status_code,
elapsed,
resp.text[:200],
)
return []
data = resp.json()
# 兼容几种可能的响应结构
code = data.get("code", data.get("status", 0))
if code not in (0, "OK", "success", 200):
logger.warning("[vision.v2] OCR 业务错误 code=%s elapsed=%.1fs resp=%s", code, elapsed, str(data)[:200])
return []
texts = _extract_texts(data)
# 去重 + 过滤空
seen: set[str] = set()
out: list[str] = []
for t in texts:
t = (t or "").strip()
if t and t not in seen and len(t) <= 100: # 过滤过长的误识别
seen.add(t)
out.append(t)
logger.info("[vision.v2] OCR 完成 elapsed=%.1fs n=%d texts=%s", elapsed, len(out), out[:5])
return out
except Exception as e:
elapsed = time.time() - t0
logger.warning("[vision.v2] OCR 异常 elapsed=%.1fs err=%s", elapsed, e, exc_info=True)
return []
def _extract_texts(data: dict) -> list[str]:
"""从 OCR 响应中抽取文本,兼容多种结构。"""
out: list[str] = []
# 常见结构1: data.texts = [{"text": "..."}, ...]
d = data.get("data") or data
if isinstance(d, dict):
for key in ("texts", "lines", "words", "items", "result"):
items = d.get(key)
if isinstance(items, list):
for it in items:
if isinstance(it, dict):
txt = it.get("text") or it.get("content") or it.get("word")
if txt:
out.append(str(txt))
elif isinstance(it, str):
out.append(it)
break
# 结构2: data.text = "..."
if not out:
t = d.get("text")
if isinstance(t, str):
out.append(t)
# 结构3: data.ocr_text / data.content
if not out:
for key in ("ocr_text", "content", "raw_text"):
v = d.get(key)
if isinstance(v, str) and v.strip():
out.append(v)
break
return out
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""V2 兜底路径:vision client(fallback 变体)单图调用,走 v8 叙述优先 prompt。
fast 超时/非 JSON/为空时单次调用;输出统一走 assembler.assemble_result 组装,
与 fast 路径同为 5 字段 image dict。
"""
from __future__ import annotations
import logging
import time
from typing import Any
from . import _prompt, assembler
logger = logging.getLogger(__name__)
_DEFAULT_TIMEOUT = 45
def call_pro_vlm(
img_url: str,
idx: int,
*,
ocr_hint: list[str] | None = None,
timeout: int = _DEFAULT_TIMEOUT,
max_tokens: int | None = None,
) -> dict[str, Any] | None:
t0 = time.time()
ocr_text = "、".join(t for t in (ocr_hint or []) if t)[:200]
try:
from packages.shared.ai_router import ai_router
client = ai_router.get_vision_client("image_analysis", variant="fallback")
if not client or not client.is_available:
logger.warning("[vision.v2] pro vision client 不可用,跳过")
return None
except Exception as e: # noqa: BLE001
logger.warning("[vision.v2] ai_router 获取失败: %s", e)
return None
system_prompt, user_prompt = _prompt.resolve_pro_prompt(img_url, ocr_text)
messages: list[dict[str, Any]] = [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": img_url}},
{"type": "text", "text": user_prompt},
],
},
]
try:
call_kwargs: dict[str, Any] = {
"messages": messages,
"images": None,
"temperature": 0.3,
"timeout": timeout,
"enable_thinking": False,
"response_format": {"type": "json_object"},
"max_tokens": max_tokens if max_tokens is not None else 4000,
}
from .json_utils import extract_json_object
obj = None
for _outer in range(2):
kw = dict(call_kwargs)
if _outer == 1:
kw.pop("response_format", None)
msgs2 = [dict(messages[0]), dict(messages[1])]
cont = [dict(c) for c in msgs2[1]["content"]]
cont[-1] = {
"type": "text",
"text": user_prompt + "\n严格只输出JSON对象,不要解释或markdown。",
}
msgs2[1] = {"role": "user", "content": cont}
kw["messages"] = msgs2
raw = client.vision_completion(**kw)
if not raw:
continue
obj = extract_json_object(raw)
if obj is not None:
break
logger.warning("[vision.v2] pro 非JSON(100字) outer=%s: %s", _outer, raw[:100])
elapsed = time.time() - t0
if obj is None:
logger.warning("[vision.v2] pro 两次均未得到JSON elapsed=%.1fs", elapsed)
return None
if obj.get("_partial"):
logger.warning("[vision.v2] pro 截断JSON(partial) elapsed=%.1fs", elapsed)
result = assembler.assemble_result(idx, obj, ocr_hint or [])
result["_source"] = "vlm_pro"
result["_fallback_used"] = True
logger.info("[vision.v2] pro 完成 model=%s elapsed=%.1fs", client.model, elapsed)
return result
except Exception as e: # noqa: BLE001
logger.warning(
"[vision.v2] pro 异常 elapsed=%.1fs err=%s",
time.time() - t0,
e,
exc_info=True,
)
return None
@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
"""V2 快速路径:vision client(默认 image_analysis 能力)强约束 JSON-only 调用。
要点:
- 通过 ai_router.get_vision_client() 获取 client;
- enable_thinking=False 关闭推理链,response_format=json_object 强约束 JSON;
- system/user prompt 优先读后台模板(v8 叙述优先),DB 不可用时用 prompts.py 默认;
- temperature=0.1(稳定输出 JSON);两次尝试(第二次去 json_object 约束)。
"""
from __future__ import annotations
import logging
import time
from typing import Any
from . import _prompt
logger = logging.getLogger(__name__)
_DEFAULT_TIMEOUT = 20
def call_fast_json(
img_url: str,
*,
timeout: int = _DEFAULT_TIMEOUT,
max_tokens: int | None = None,
) -> dict[str, Any] | None:
t0 = time.time()
try:
from packages.shared.ai_router import ai_router
client = ai_router.get_vision_client("image_analysis", variant="primary")
if not client or not client.is_available:
logger.warning("[vision.v2] vision client 不可用,跳过 fast_json")
return None
except Exception as e: # noqa: BLE001
logger.warning("[vision.v2] ai_router 获取失败: %s", e)
return None
system_prompt, user_prompt = _prompt.resolve_fast_prompt(img_url, "")
messages: list[dict[str, Any]] = [
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": img_url}},
{"type": "text", "text": user_prompt},
],
},
]
try:
call_kwargs: dict[str, Any] = {
"messages": messages,
"images": None,
"temperature": 0.1,
"timeout": timeout,
"enable_thinking": False,
"response_format": {"type": "json_object"},
}
if max_tokens is not None:
call_kwargs["max_tokens"] = max_tokens
from .json_utils import extract_json_object
obj = None
for _outer in range(2):
kw = dict(call_kwargs)
if _outer == 1:
kw.pop("response_format", None)
msgs2 = [dict(messages[0]), dict(messages[1])]
cont = [dict(c) for c in msgs2[1]["content"]]
cont[-1] = {
"type": "text",
"text": user_prompt + "\n严格只输出JSON对象,不要解释或markdown。",
}
msgs2[1] = {"role": "user", "content": cont}
kw["messages"] = msgs2
raw = client.vision_completion(**kw)
if not raw:
continue
obj = extract_json_object(raw)
if obj is not None:
break
logger.warning("[vision.v2] fast_json 非JSON(100字) outer=%s: %s", _outer, raw[:100])
elapsed = time.time() - t0
if obj is None:
logger.warning("[vision.v2] fast_json 两次均未得到JSON elapsed=%.1fs", elapsed)
return None
if obj.get("_partial"):
logger.warning("[vision.v2] fast_json 截断JSON(partial) elapsed=%.1fs", elapsed)
logger.info(
"[vision.v2] fast_json 完成 model=%s elapsed=%.1fs type=%s",
client.model,
elapsed,
obj.get("type"),
)
return obj
except Exception as e: # noqa: BLE001
logger.warning(
"[vision.v2] fast_json 异常 elapsed=%.1fs err=%s",
time.time() - t0,
e,
exc_info=True,
)
return None
+26 -3
View File
@@ -241,19 +241,35 @@ DOUBAO_API_KEY=${DOUBAO_API_KEY}
# 模型 Endpoint ID(在 ARK 控制台创建推理接入点后获得)
DOUBAO_MODEL=${DOUBAO_MODEL}
DOUBAO_FAST_MODEL=${DOUBAO_FAST_MODEL}
# API Base URL
DOUBAO_BASE_URL=${DOUBAO_BASE_URL}
# 请求超时(秒)
DOUBAO_TIMEOUT=60
DOUBAO_TIMEOUT=${DOUBAO_TIMEOUT}
# 最大重试次数
DOUBAO_MAX_RETRIES=2
DOUBAO_MAX_RETRIES=${DOUBAO_MAX_RETRIES}
# 视觉模型 Endpoint ID(支持图片/视频理解的模型)
# 视觉模型(支持图片/视频理解的模型,model name 格式)
DOUBAO_VISION_MODEL=${DOUBAO_VISION_MODEL}
# 快速视觉模型(viral-video 图片分析 lite 路径)
DOUBAO_VISION_LITE_MODEL=${DOUBAO_VISION_LITE_MODEL}
# 是否启用 lite 视觉路径(true/false)
DOUBAO_VISION_USE_LITE=${DOUBAO_VISION_USE_LITE}
# 信任链文生图模型(Seedream)
DOUBAO_IMAGE_MODEL=${DOUBAO_IMAGE_MODEL}
# 文生图尺寸
DOUBAO_IMAGE_SIZE=${DOUBAO_IMAGE_SIZE}
# 文生图超时(秒)
DOUBAO_IMAGE_TIMEOUT=${DOUBAO_IMAGE_TIMEOUT}
# ==================== 微信开放平台 OAuth(网页扫码登录)====================
# 回调域名:xiaoxiajianji.com(微信开放平台已配置)
@@ -295,3 +311,10 @@ GPU_ENCODE_CRF=23
GPU_ENCODE_FALLBACK_CPU=true
GPU_ENCODE_MEZZANINE_TRANSPORT=oss
GPU_ENCODE_OSS_TMP_PREFIX=tmp/gpu-mezzanine/
# ==================== Ditto 蚂蚁数字人口型 ====================
# 注意:这些值必须写死在模板里(不是 CI Secret),否则每次 CI 重新渲染 .env 都会被丢弃,
# 导致 staging 发版后 Ditto 口型服务静默降级到 GPU/MediaKit(P0 防复发)。
USE_DITTO_LIPSYNC=true
DITTO_API_BASE_URL=http://100.76.80.23:8000
DITTO_DEFAULT_VIDEO_URL=https://xiaoxia-autocut.oss-cn-hangzhou.aliyuncs.com/uploads/default_avatar.mp4
+23 -7
View File
@@ -335,6 +335,10 @@ class GenerationTaskModel(Base):
bgm_config = Column(JSON, nullable=False, default=dict)
extra_meta = Column("metadata", JSON, nullable=False, default=dict)
logs = Column(Text, nullable=False, default="[]", server_default="[]")
# 功能计费(smart_edit):预扣积分 / 最终积分 / 预扣流水 ID
credits_prepaid = Column(Float, nullable=False, default=0.0, server_default="0")
credits_cost = Column(Float, nullable=False, default=0.0, server_default="0")
credits_transaction_id = Column(String(36), nullable=False, default="", server_default="")
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(UTC))
updated_at = Column(
DateTime,
@@ -727,6 +731,11 @@ class LipsyncJobModel(Base):
# 精确句子时间戳(TTS 合成后由 silencedetect 计算,用于 B-roll 精确定位)
sentence_timings = Column(JSON, nullable=True) # list[{index,text,start_time,end_time}]
# 功能计费(lip_sync):预扣积分 / 最终积分 / 预扣流水 ID
credits_prepaid = Column(Float, nullable=False, default=0.0, server_default="0")
credits_cost = Column(Float, nullable=False, default=0.0, server_default="0")
credits_transaction_id = Column(String(36), nullable=False, default="", server_default="")
# 时间戳
submitted_at = Column(DateTime, nullable=True)
completed_at = Column(DateTime, nullable=True)
@@ -905,6 +914,11 @@ class GpuLipsyncTaskModel(Base):
# 心跳:worker 最近一次 poll/result 的时间,用于判定 worker 失联
last_heartbeat_at = Column(DateTime, nullable=True)
# 功能计费(lip_sync):预扣积分 / 最终积分 / 预扣流水 ID
credits_prepaid = Column(Float, nullable=False, default=0.0, server_default="0")
credits_cost = Column(Float, nullable=False, default=0.0, server_default="0")
credits_transaction_id = Column(String(36), nullable=False, default="", server_default="")
class GpuWorkerModel(Base):
"""GPU Worker 注册表 — 反向轮询模式下用于心跳与监控."""
@@ -928,6 +942,7 @@ class ViralVideoJobModel(Base):
id = Column(String(36), primary_key=True)
user_id = Column(String(36), nullable=False, index=True)
images = Column(JSON, nullable=False, default=list) # 产品图片 URL 列表
pre_trusted_images = Column(JSON, nullable=True) # #2172 信任链预热结果(Seedream AI 化 URL 列表)
industry = Column(String(100), nullable=False, default="")
target_customer = Column(String(500), nullable=False, default="")
persona_id = Column(String(36), nullable=False, default="")
@@ -990,16 +1005,17 @@ class ViralVideoStyleTemplateModel(Base):
class ViralVideoPromptTemplateModel(Base):
"""爆款视频 Prompt 模板表(由 #2040 seed)"""
"""爆款视频 Prompt 模板表(#2040:纯文本 XML 标签模板,运营可直接编辑)"""
__tablename__ = "viral_video_prompt_templates"
id = Column(String(36), primary_key=True)
prompt_type = Column(String(50), nullable=False, index=True)
name = Column(String(200), nullable=False)
content = Column(Text, nullable=False, default="")
variables = Column(JSON, nullable=False, default=list)
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(128), nullable=False)
prompt_type = Column(String(32), nullable=False)
version = Column(Integer, nullable=False, default=1)
is_active = Column(Boolean, nullable=False, default=True, index=True)
system_prompt = Column(Text, nullable=False)
user_prompt_template = Column(Text, nullable=False)
example_output = Column(Text, nullable=True)
is_active = Column(Boolean, nullable=False, default=True)
created_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC))
updated_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC))
@@ -6,18 +6,33 @@ from sqlalchemy.orm import Session
from packages.adapters.sqlalchemy_impl.models import (
ViralVideoJobModel,
ViralVideoPromptTemplateModel,
ViralVideoStyleTemplateModel,
)
from packages.domain.viral_video import ViralVideoJob, ViralVideoStatus
def _to_domain(model: ViralVideoJobModel) -> ViralVideoJob:
"""ORM → 领域实体。"""
"""ORM → 领域实体。pre_trusted_images 兼容脏数据:双序列化字符串/字符数组/list[str]。"""
import json as _pti_json
_raw_pti = getattr(model, "pre_trusted_images", None)
_pti: list[str] | None = None
if _raw_pti is not None:
if isinstance(_raw_pti, str):
try:
_p = _pti_json.loads(_raw_pti)
if isinstance(_p, list):
_pti = [u for u in _p if isinstance(u, str) and u] or None
except Exception:
_pti = None
elif isinstance(_raw_pti, list):
_f = [u for u in _raw_pti if isinstance(u, str) and len(u) > 5]
_pti = _f if _f else None
return ViralVideoJob(
id=model.id,
user_id=model.user_id,
images=list(model.images or []),
pre_trusted_images=_pti,
industry=model.industry or "",
target_customer=model.target_customer or "",
persona_id=model.persona_id or "",
@@ -70,6 +85,7 @@ class SQLAlchemyViralVideoJobRepository:
id=job.id,
user_id=job.user_id,
images=job.images,
pre_trusted_images=job.pre_trusted_images,
industry=job.industry,
target_customer=job.target_customer,
persona_id=job.persona_id,
@@ -126,6 +142,7 @@ class SQLAlchemyViralVideoJobRepository:
model.storyboard = job.storyboard
model.generated_copy_text = job.generated_copy_text or ""
model.copy_result = job.copy_result
model.pre_trusted_images = job.pre_trusted_images
model.result_video_url = job.result_video_url
model.video_resolution = getattr(job, "video_resolution", "720p") or "720p"
model.credits_prepaid = float(getattr(job, "credits_prepaid", 0) or 0)
@@ -227,31 +244,3 @@ class SQLAlchemyViralVideoStyleTemplateRepository:
"style_config": dict(model.style_config) if model.style_config else {},
"is_system": model.is_system,
}
class SQLAlchemyViralVideoPromptTemplateRepository:
"""Prompt 模板仓储(由 #2040 seed,这里只读取)。"""
def __init__(self, session: Session):
self.session = session
def get_active_by_type(self, prompt_type: str) -> dict | None:
model = (
self.session.query(ViralVideoPromptTemplateModel)
.filter(
ViralVideoPromptTemplateModel.prompt_type == prompt_type,
ViralVideoPromptTemplateModel.is_active.is_(True),
)
.order_by(ViralVideoPromptTemplateModel.version.desc())
.first()
)
if model is None:
return None
return {
"id": model.id,
"prompt_type": model.prompt_type,
"name": model.name,
"content": model.content,
"variables": list(model.variables or []),
"version": model.version,
}
+1
View File
@@ -0,0 +1 @@
"""应用层:对外展示目录(套餐/积分包)。"""
@@ -0,0 +1,152 @@
"""读取管理后台配置的会员套餐 / 积分充值包(共享库真实数据)。
替代旧的硬编码 MEMBERSHIP_PRICES / POINTS_PACKAGES。
短 TTL 缓存(30 秒),后台改价/启停后用户端最多 30 秒可见。
"""
from __future__ import annotations
import threading
import time
from typing import Any
_CACHE_TTL = 30.0
_lock = threading.Lock()
_cache: dict[str, tuple[float, Any]] = {}
_QUOTA_LABELS = {
"4k": "4K 超清分辨率",
"batch_render": "批量渲染",
"priority_queue": "优先处理队列",
"ai_matting": "AI 智能抠像",
"remove_watermark": "去水印",
}
def _cached(key: str, loader):
now = time.time()
hit = _cache.get(key)
if hit and now - hit[0] < _CACHE_TTL:
return hit[1]
with _lock:
hit = _cache.get(key)
if hit and time.time() - hit[0] < _CACHE_TTL:
return hit[1]
value = loader()
_cache[key] = (time.time(), value)
return value
def _quota_features(quotas: dict[str, Any] | None) -> dict[str, Any]:
quotas = quotas or {}
features: dict[str, Any] = {}
for k, v in quotas.items():
if k == "credits_per_month":
features["credits_per_month"] = v
elif k in _QUOTA_LABELS:
features[_QUOTA_LABELS[k]] = v
else:
features[k] = v
return features
def get_membership_plans() -> list[dict[str, Any]]:
"""读取 is_enabled=true 的套餐,按年/月周期展开为用户端档位。"""
def _load() -> list[dict[str, Any]]:
from sqlalchemy import text
from packages.adapters.sqlalchemy_impl.session import SessionLocal
if SessionLocal is None:
return []
session = SessionLocal()
try:
rows = session.execute(text("""
SELECT plan_key, name, description, monthly_price, yearly_price,
quotas, display_order
FROM plans
WHERE is_enabled = TRUE
ORDER BY display_order NULLS LAST, created_at
""")).fetchall()
finally:
session.close()
plans: list[dict[str, Any]] = []
for r in rows:
base_features = _quota_features(r.quotas if isinstance(r.quotas, dict) else None)
if r.yearly_price and float(r.yearly_price) > 0:
plans.append(
{
"plan_id": r.plan_key,
"billing_cycle": "yearly",
"name": r.name,
"description": r.description,
"price_cents": int(round(float(r.yearly_price) * 100)),
"monthly_price_cents": int(round(float(r.yearly_price) * 100 / 12)),
"duration_days": 365,
"features": dict(base_features),
}
)
if r.monthly_price and float(r.monthly_price) > 0:
plans.append(
{
"plan_id": r.plan_key,
"billing_cycle": "monthly",
"name": r.name,
"description": r.description,
"price_cents": int(round(float(r.monthly_price) * 100)),
"monthly_price_cents": int(round(float(r.monthly_price) * 100)),
"duration_days": 30,
"features": dict(base_features),
}
)
return plans
return _cached("membership_plans", _load)
def get_points_packages() -> list[dict[str, Any]]:
"""读取 is_active=true 的积分充值包。"""
def _load() -> list[dict[str, Any]]:
from sqlalchemy import text
from packages.adapters.sqlalchemy_impl.session import SessionLocal
if SessionLocal is None:
return []
session = SessionLocal()
try:
rows = session.execute(text("""
SELECT package_key, name, price, credits, bonus_credits,
is_recommended, description, sort_order
FROM credit_packages
WHERE is_active = TRUE
ORDER BY sort_order NULLS LAST, price
""")).fetchall()
finally:
session.close()
packages: list[dict[str, Any]] = []
for r in rows:
total_points = int(r.credits or 0) + int(r.bonus_credits or 0)
price_cents = int(round(float(r.price) * 100))
unit = (price_cents / 100 / total_points) if total_points else 0
packages.append(
{
"code": r.package_key,
"name": r.name,
"points": total_points,
"bonus_credits": int(r.bonus_credits or 0),
"price_cents": price_cents,
"unit_price": f"¥{unit:.3f}/积分",
"is_recommended": bool(r.is_recommended),
"description": r.description,
}
)
return packages
return _cached("points_packages", _load)
+17 -4
View File
@@ -351,12 +351,25 @@ class CosyVoiceService:
用于私有 bucket 下,将裸 URL 转为预签名 URL,
确保 CosyVoice 服务器能下载参考音频.
"""
# 优先从 ai_router 获取 DB 配置
_router_key, _router_url, _router_model = "", "", ""
try:
from packages.shared.ai_router import ai_router
tts_client = ai_router.get_tts_client("tts")
if tts_client and tts_client.is_available:
_router_key = tts_client.api_key
_router_url = tts_client.base_url
_router_model = tts_client.model
except Exception:
pass
settings = get_shared_settings()
self._api_key = api_key or settings.cosyvoice_api_key
self._base_url = base_url or settings.cosyvoice_base_url
self._model = model or settings.cosyvoice_model
self._clone_model = clone_model or getattr(settings, "cosyvoice_clone_model", "voice-enrollment")
self._api_key = api_key or _router_key or settings.cosyvoice_api_key
self._base_url = base_url or _router_url or settings.cosyvoice_base_url
self._model = model or _router_model or settings.cosyvoice_model
self._clone_model = clone_model or getattr(settings, "cosyvoice_clone_model", "")
self._audio_url_signer = audio_url_signer
# base_url 规范化:去掉末尾的路径残留(兼容旧版配置)
@@ -0,0 +1,316 @@
"""Ditto LLM 情绪分析服务 — #2076 后续:根据文案生成 emo_timeline.
职责:
1. 正则按 。!?; 初步分句
2. 调 DoubaoClient.chat_completion 分析每句表情(emo: 0-7, intensity: 0-1)
3. 结果 LRU 缓存(文案 hash → 情绪列表)
4. LLM 失败/超时/格式错 → 返回空列表(降级中性表情,不阻塞生成)
5. TTS 完成后按字数比例或 sentence_timings 对齐成秒级 timeline
"""
from __future__ import annotations
import hashlib
import json
import logging
import re
from functools import lru_cache
from pathlib import Path
from typing import Any, Optional
logger = logging.getLogger(__name__)
# ── 表情常量 ─────────────────────────────────────────────────────
EMO_ANGER = 0
EMO_DISGUST = 1
EMO_FEAR = 2
EMO_HAPPY = 3
EMO_NEUTRAL = 4
EMO_SAD = 5
EMO_SURPRISE = 6
EMO_CONTEMPT = 7
ALLOWED_EMOS = {EMO_HAPPY, EMO_NEUTRAL, EMO_SAD, EMO_SURPRISE} # 营销场景白名单
# ── 分句正则 ─────────────────────────────────────────────────────
_SENT_SPLIT_RE = re.compile(r"(?<=[。!?;!?;])\s*")
# ── 默认 prompt 模板文件路径 ──────────────────────────────────────
_DEFAULT_PROMPT_PATH = Path(__file__).parent / "prompts" / "ditto_emotion.txt"
def _load_default_prompt() -> str:
try:
return _DEFAULT_PROMPT_PATH.read_text(encoding="utf-8").strip()
except Exception:
# 文件不存在时用极简兜底
return (
"分析文案每句话表情,输出JSON数组:"
'[{"text":"句子","emo":4,"intensity":0.2}],emo:3开心4中性5伤心6惊讶,'
"禁止0/1/2/7。\n【文案】\n{文案}"
)
# ── 数据结构 ─────────────────────────────────────────────────────
class EmotionSegment:
"""单句情绪结果(LLM 输出的原始结构)."""
__slots__ = ("text", "emo", "intensity")
def __init__(self, text: str, emo: int, intensity: float):
self.text = text
self.emo = emo
self.intensity = intensity
def to_dict(self) -> dict[str, Any]:
return {"text": self.text, "emo": self.emo, "intensity": self.intensity}
class EmotionTimelineEntry:
"""对齐到音频时间轴后的情绪片段(传给 Ditto)."""
__slots__ = ("start", "end", "emo", "intensity")
def __init__(self, start: float, end: float, emo: int, intensity: float):
self.start = round(start, 2)
self.end = round(end, 2)
self.emo = emo
self.intensity = round(intensity, 2)
def to_dict(self) -> dict[str, Any]:
return {
"start": self.start,
"end": self.end,
"emo": self.emo,
"intensity": self.intensity,
}
# ── 分句 ─────────────────────────────────────────────────────────
def split_sentences(text: str) -> list[str]:
"""按中文句末标点切分,过滤空串."""
if not text:
return []
parts = _SENT_SPLIT_RE.split(text.strip())
return [p.strip() for p in parts if p and p.strip()]
# ── 解析 LLM 返回的 JSON ─────────────────────────────────────────
def _parse_emotion_json(raw: str) -> list[EmotionSegment]:
"""解析 LLM 返回,容错处理:
- 去掉 markdown 代码块包裹
- 只取第一个 JSON 数组
- 逐行校验 emo/intensity 合法性,过滤无效项
"""
if not raw:
return []
text = raw.strip()
# 去掉 ```json ... ``` 包裹
if text.startswith("```"):
text = re.sub(r"^```(?:json)?\s*", "", text)
text = re.sub(r"\s*```$", "", text)
# 找第一个 [ 到最后一个 ]
lb = text.find("[")
rb = text.rfind("]")
if lb == -1 or rb == -1 or rb <= lb:
return []
try:
data = json.loads(text[lb : rb + 1])
except (json.JSONDecodeError, ValueError):
return []
if not isinstance(data, list):
return []
results: list[EmotionSegment] = []
for item in data:
if not isinstance(item, dict):
continue
try:
emo = int(item.get("emo", EMO_NEUTRAL))
intensity = float(item.get("intensity", 0.2))
except (TypeError, ValueError):
continue
if emo not in ALLOWED_EMOS:
emo = EMO_NEUTRAL
intensity = max(0.05, min(1.0, intensity))
sent_text = str(item.get("text", "")).strip()
if not sent_text:
continue
results.append(EmotionSegment(text=sent_text, emo=emo, intensity=intensity))
return results
# ── 时间对齐(按字数比例)────────────────────────────────────────
def align_timeline_by_length(
segments: list[EmotionSegment],
audio_duration: float,
) -> list[EmotionTimelineEntry]:
"""按各句字数占总字数比例分配 audio_duration 时长."""
if not segments or audio_duration <= 0:
return []
total_chars = sum(len(s.text) for s in segments)
if total_chars <= 0:
return []
entries: list[EmotionTimelineEntry] = []
pos = 0.0
for i, seg in enumerate(segments):
if i == len(segments) - 1:
end = audio_duration # 最后一段到结尾,避免浮点误差
else:
end = pos + (len(seg.text) / total_chars) * audio_duration
if end > pos:
entries.append(
EmotionTimelineEntry(
start=pos,
end=end,
emo=seg.emo,
intensity=seg.intensity,
)
)
pos = end
return entries
def align_timeline_by_timings(
segments: list[EmotionSegment],
sentence_timings: list[dict[str, Any]],
audio_duration: float,
) -> list[EmotionTimelineEntry]:
"""使用 TTS sentence_timings 精确对齐(优先方案).
sentence_timings 格式:[{"start":0.0,"end":1.2,"text":"句子"}, ...]
按句序匹配 segments 和 timings,长度不一致时回退到按字数比例。
"""
if not sentence_timings or len(sentence_timings) != len(segments):
return align_timeline_by_length(segments, audio_duration)
entries: list[EmotionTimelineEntry] = []
for seg, timing in zip(segments, sentence_timings, strict=False):
try:
start = float(timing.get("start", 0))
end = float(timing.get("end", 0))
except (TypeError, ValueError):
return align_timeline_by_length(segments, audio_duration)
if end <= start:
continue
entries.append(
EmotionTimelineEntry(
start=start,
end=end,
emo=seg.emo,
intensity=seg.intensity,
)
)
return entries
# ── LLM 情绪分析服务 ─────────────────────────────────────────────
class DittoEmotionService:
"""Ditto 情绪分析服务(带 LRU 缓存)."""
def __init__(self, settings=None):
from packages.config import get_api_settings
self.settings = settings or get_api_settings()
self._client = None
@property
def enabled(self) -> bool:
return bool(getattr(self.settings, "ditto_emotion_enabled", False))
def _get_prompt_template(self) -> str:
"""优先用配置(环境变量),否则读文件."""
cfg_prompt = getattr(self.settings, "ditto_emotion_prompt", "") or ""
if cfg_prompt.strip():
return cfg_prompt.strip()
return _load_default_prompt()
def _cache_key(self, text: str) -> str:
return hashlib.md5(text.strip().encode("utf-8")).hexdigest()
def _get_llm_client(self):
if self._client is None:
from packages.shared.ai_client import get_doubao_client
self._client = get_doubao_client()
return self._client
def _call_llm(self, text: str) -> list[EmotionSegment]:
"""调 LLM 分析情绪,失败返回空列表."""
template = self._get_prompt_template()
prompt = template.replace("{文案}", text)
messages = [{"role": "user", "content": prompt}]
model = getattr(self.settings, "ditto_emotion_model", "") or None
temperature = getattr(self.settings, "ditto_emotion_temperature", 0.1)
timeout = getattr(self.settings, "ditto_emotion_timeout", 10)
max_tokens = getattr(self.settings, "ditto_emotion_max_tokens", 1024)
try:
client = self._get_llm_client()
result = client.chat_completion(
messages=messages,
model=model,
temperature=temperature,
max_tokens=max_tokens,
timeout=timeout,
)
except Exception as exc:
logger.warning("[ditto_emotion] LLM 调用异常: %s", exc)
return []
if not result:
return []
segments = _parse_emotion_json(result)
if not segments:
logger.warning("[ditto_emotion] LLM 返回解析失败: %s", result[:200])
return segments
def analyze(self, text: str) -> list[EmotionSegment]:
"""分析文案情绪(带缓存),失败返回空列表."""
if not self.enabled or not text or not text.strip():
return []
key = self._cache_key(text)
return _cached_analyze(self, key, text)
def build_timeline(
self,
text: str,
audio_duration: float,
sentence_timings: Optional[list[dict[str, Any]]] = None,
) -> str:
"""完整流程:分句→LLM分析→时间对齐→序列化为JSON字符串.
返回: JSON 字符串(可直接传 Ditto emo_timeline 参数);空字符串表示降级中性。
"""
segments = self.analyze(text)
if not segments:
return ""
if sentence_timings:
entries = align_timeline_by_timings(segments, sentence_timings, audio_duration)
else:
entries = align_timeline_by_length(segments, audio_duration)
if not entries:
return ""
return json.dumps([e.to_dict() for e in entries], ensure_ascii=False)
# ── 模块级 LRU 缓存实例 ─────────────────────────────────────────
# 每个 service 实例共享缓存(按 cache_key 区分)
@lru_cache(maxsize=512)
def _cached_analyze(service: DittoEmotionService, cache_key: str, text: str) -> list[EmotionSegment]:
"""LRU 缓存包装:cache_key 由文案 hash 生成,maxsize 从配置读."""
# 注意:service 参数仅用于传递调用,缓存由 cache_key 驱动
segments = service._call_llm(text)
# 如果 LLM 返回空(比如分句数量不匹配),尝试直接对预分句结果分析
if not segments:
pre_splits = split_sentences(text)
if len(pre_splits) > 1:
# 用预分句结果兜底:全中性低强度
segments = [EmotionSegment(text=s, emo=EMO_NEUTRAL, intensity=0.1) for s in pre_splits]
return segments
_singleton: Optional[DittoEmotionService] = None
def get_ditto_emotion_service() -> DittoEmotionService:
global _singleton
if _singleton is None:
_singleton = DittoEmotionService()
return _singleton
+291
View File
@@ -0,0 +1,291 @@
"""蚂蚁 Ditto 数字人口型 API 客户端 — #2076.
封装 Ditto FastAPI(部署在 5060Ti GPU 节点,Tailscale 内网可达):
- GET /health 健康检查
- POST /generate 生成口型视频(同步返回 MP4 流)
关键特性:
- 入参:video_url(人物模板视频 URL) + audio_url(TTS 音频 URL) + script(文案原文)
- 出参:直接返回 video/mp4 字节流(自带音频,无需二次混流)
- 429 时指数退避重试(最多 ditto_max_retries 次)
- 500/超时视为失败
- 输出 MP4 字节流转存到自家 OSS,返回公网 URL
注意:
- 保留 MuseTalk/GPU 路径不变;本服务作为更高优先级的第三条口型路径
- 不传 emotion/表情精细控制,使用默认 emo_global=4(中性)+ use_script_emo=true(关键词驱动表情)
- Ditto 输出自带音视频,不需要 GFPGAN 超分,不需要 ffmpeg 音视频混流
"""
from __future__ import annotations
import io
import logging
import time
from dataclasses import dataclass
from typing import Optional
import httpx
from packages.config import get_api_settings
logger = logging.getLogger(__name__)
class DittoError(Exception):
"""Ditto API 调用失败."""
def __init__(self, message: str, code: str = "DittoError", status_code: int = 0):
self.code = code
self.status_code = status_code
super().__init__(message)
@dataclass
class DittoResult:
"""Ditto 生成结果."""
video_bytes: bytes
video_url: str = "" # 转存 OSS 后填充
elapsed_seconds: float = 0.0
rtf: float = 0.0 # 实时率(响应头 X-RTF)
frames: int = 0 # 帧数(响应头 X-Frames)
class DittoClient:
"""蚂蚁 Ditto 数字人口型 API 客户端."""
def __init__(
self,
base_url: Optional[str] = None,
default_video_url: Optional[str] = None,
max_retries: Optional[int] = None,
timeout: Optional[int] = None,
):
s = get_api_settings()
self.base_url = (base_url or s.ditto_api_base_url or "").rstrip("/")
self.default_video_url = default_video_url or s.ditto_default_video_url or ""
self.max_retries = int(max_retries if max_retries is not None else s.ditto_max_retries)
self.timeout = int(timeout if timeout is not None else s.ditto_request_timeout)
self.blend_frames = int(s.ditto_blend_frames)
@property
def is_configured(self) -> bool:
"""配置是否完整(base_url + 默认模板视频都有值)."""
return bool(self.base_url) and bool(self.default_video_url)
def health(self) -> bool:
"""健康检查;成功返回 True,失败返回 False(不抛异常)."""
if not self.base_url:
return False
url = f"{self.base_url}/health"
try:
with httpx.Client(timeout=5.0) as client:
resp = client.get(url)
ok = resp.status_code == 200
if ok:
logger.info("[ditto] health check OK: %s", url)
else:
logger.warning("[ditto] health check status=%d: %s", resp.status_code, url)
return ok
except Exception as exc:
logger.warning("[ditto] health check failed: %s", exc)
return False
def generate(
self,
*,
audio_url: str,
script: str,
video_url: Optional[str] = None,
emo_global: int = 4,
use_script_emo: bool = True,
blend_frames: Optional[int] = None,
emo_timeline: str = "",
) -> DittoResult:
"""调用 Ditto /generate 接口,返回 MP4 字节流结果.
Raises DittoError on failure.
"""
if not self.base_url:
raise DittoError("DITTO_API_BASE_URL 未配置", code="ConfigMissing")
driver_url = video_url or self.default_video_url
if not driver_url:
raise DittoError("Ditto 人物模板视频 URL 未配置", code="ConfigMissing")
if not audio_url:
raise DittoError("audio_url 不能为空", code="InvalidParam")
if not script:
script = " "
_blend = blend_frames if blend_frames is not None else self.blend_frames
payload = {
"video_url": driver_url,
"audio_url": audio_url,
"script": script,
"emo_global": emo_global,
"use_script_emo": use_script_emo,
"blend_frames": _blend,
}
if emo_timeline:
payload["emo_timeline"] = emo_timeline
url = f"{self.base_url}/generate"
last_exc: Optional[Exception] = None
for attempt in range(self.max_retries + 1):
try:
start = time.monotonic()
# 精细化超时:connect=10s(网络不通快速失败),read=120s(最长音频~45s按RTF=2.8推算)
_timeout = httpx.Timeout(connect=10.0, read=self.timeout, write=30.0, pool=10.0)
with httpx.Client(timeout=_timeout, follow_redirects=True) as client:
resp = client.post(url, json=payload)
elapsed = time.monotonic() - start
if resp.status_code == 429:
wait = min(2**attempt, 30)
logger.warning(
"[ditto] GPU 繁忙 (429),%ds 后重试 (%d/%d)",
wait,
attempt + 1,
self.max_retries,
)
if attempt >= self.max_retries:
raise DittoError(
f"Ditto GPU 繁忙,重试 {self.max_retries} 次仍失败",
code="BusyRetriesExhausted",
status_code=429,
)
time.sleep(wait)
continue
if resp.status_code != 200:
_text = (resp.text or "")[:300]
logger.error(
"[ditto] generate 失败 status=%d attempt=%d body=%s",
resp.status_code,
attempt + 1,
_text,
)
if resp.status_code >= 500 and attempt < self.max_retries:
time.sleep(min(2**attempt, 15))
continue
raise DittoError(
f"Ditto 返回 {resp.status_code}: {_text}",
code="DittoAPIError",
status_code=resp.status_code,
)
video_bytes = resp.content
if not video_bytes or len(video_bytes) < 1024:
raise DittoError(
f"Ditto 返回内容异常(size={len(video_bytes) if video_bytes else 0})",
code="EmptyResponse",
)
try:
rtf = float(resp.headers.get("X-RTF", "0") or 0)
except ValueError:
rtf = 0.0
try:
frames = int(resp.headers.get("X-Frames", "0") or 0)
except ValueError:
frames = 0
try:
x_time = float(resp.headers.get("X-Time", "0") or 0)
if x_time > 0:
elapsed = x_time
except ValueError:
pass
logger.info(
"[ditto] generate 成功 size=%d rtf=%.2f frames=%d elapsed=%.1fs attempt=%d",
len(video_bytes),
rtf,
frames,
elapsed,
attempt + 1,
)
return DittoResult(
video_bytes=video_bytes,
elapsed_seconds=elapsed,
rtf=rtf,
frames=frames,
)
except DittoError:
raise
except (httpx.ConnectError, httpx.NetworkError, ConnectionError, OSError) as exc:
# 网络不通/连接被拒(如 GPU 断网/Tailscale 掉线),不重试,直接快速回退
logger.warning("[ditto] 网络不可达 attempt=%d err=%s", attempt + 1, exc)
raise DittoError(
f"Ditto 网络不可达: {exc}",
code="NetworkUnreachable",
) from exc
except httpx.TimeoutException as exc:
last_exc = exc
logger.warning("[ditto] 请求超时 attempt=%d err=%s", attempt + 1, exc)
if attempt < self.max_retries:
time.sleep(min(2**attempt, 15))
continue
raise DittoError(
f"Ditto 请求超时(read={self.timeout}s),重试耗尽",
code="Timeout",
) from exc
except Exception as exc:
last_exc = exc
logger.warning("[ditto] 请求异常 attempt=%d err=%s", attempt + 1, exc)
if attempt < self.max_retries:
time.sleep(min(2**attempt, 10))
continue
raise DittoError(f"Ditto 调用异常: {exc}", code="NetworkError") from exc
raise DittoError("Ditto 未知错误", code="Unknown") from last_exc
def generate_and_persist(
self,
*,
job_id: str,
user_id: str,
audio_url: str,
script: str,
video_url: Optional[str] = None,
emo_timeline: str = "",
blend_frames: Optional[int] = None,
) -> DittoResult:
"""调用 generate 并把 MP4 转存到自家 OSS,返回带 video_url 的结果."""
result = self.generate(
audio_url=audio_url,
script=script,
video_url=video_url,
emo_timeline=emo_timeline,
blend_frames=blend_frames,
)
try:
from packages.shared.storage import get_shared_storage_service
storage = get_shared_storage_service()
storage_key = f"ditto-output/{user_id}/{job_id}.mp4"
public_url = storage.upload_file(
io.BytesIO(result.video_bytes),
storage_key,
content_type="video/mp4",
)
result.video_url = public_url
logger.info(
"[ditto] 转存 OSS 完成 job=%s key=%s",
job_id,
storage_key,
)
except Exception as exc:
logger.error("[ditto] 转存 OSS 失败 job=%s err=%s", job_id, exc, exc_info=True)
raise DittoError(f"Ditto 结果转存 OSS 失败: {exc}", code="StorageError") from exc
return result
_ditto_client_singleton: Optional[DittoClient] = None
def get_ditto_client() -> DittoClient:
"""获取 DittoClient 单例(简易工厂,便于单测 mock)."""
global _ditto_client_singleton
if _ditto_client_singleton is None:
_ditto_client_singleton = DittoClient()
return _ditto_client_singleton
@@ -0,0 +1,27 @@
你是一个数字人视频表情导演。给定一段口播文案,分析每句话应该用什么表情和强度,让数字人说话时表情自然有变化,不僵硬。
【表情编号】
0=愤怒(营销场景禁用)
1=厌恶(禁用)
2=害怕(禁用)
3=开心:介绍优点、优惠、好消息、号召行动时用
4=中性:默认表情,陈述事实、平铺直叙时用
5=伤心:仅在共情用户痛点时低强度使用(如"是不是经常遇到…")
6=惊讶:惊喜、意外、强调价值时用(如"居然""只要""竟然")
7=轻蔑(禁用)
【强度说明】
0.1-0.2:几乎看不出变化,比中性多一点情绪色彩
0.3-0.4:有明显但自然的情绪,正常说话的波动
0.5-0.6:较强情绪,感叹句/重点强调
0.7+:极强情绪,极少使用
【规则】
1. 按自然语义分句,以。!?;为主要分界,逗号不分
2. 60-70%的句子应该用中性(4),不要每句都标情绪
3. 情绪和内容匹配:卖点→开心(3),痛点共情→伤心(5)低强度,惊喜/划算→惊讶(6),陈述→中性(4)
4. 相邻句子情绪不要剧烈跳变
5. 感叹号结尾强度0.4-0.6,句号结尾一般0.1-0.3
6. 开头结尾句用中性(4)或低强度开心(3)
7. 禁止使用0/1/2/7
【输出格式】严格JSON数组,不要输出其他内容
[{"text":"句子原文","emo":3,"intensity":0.4}]
【文案】
{文案}
@@ -0,0 +1 @@
"""应用层:爆款视频 Prompt 模板系统(#2040)。"""
@@ -0,0 +1,427 @@
"""爆款视频 5 步编排:图片分析 → 意图解析 → 文案融合 → 分镜 → 审核重写。
所有 LLM 调用走 DoubaoClient,单测通过 client 参数注入 mock,不真调 API。
任何一步解析失败都走规则 fallback,不抛异常阻断。
"""
from __future__ import annotations
import logging
from typing import Optional
from packages.application.viral_video import xml_parser as xp
from packages.application.viral_video.prompt_loader import (
PromptTemplate,
get_template,
render_system_prompt,
render_user_prompt,
)
from packages.application.viral_video.prompts import (
FUSION_INSTRUCTIONS,
GLOBAL_CONSTRAINTS,
NEGATIVE_RULES,
)
from packages.application.viral_video.reviewer import Reviewer
from packages.application.viral_video.schemas import (
BodyPoint,
Clip,
ColorItem,
CoreMessage,
FusionResult,
ImageAnalysis,
IntentResult,
KenBurns,
PersonalBrand,
ProductItem,
ReviewResult,
ScriptSegment,
Storyboard,
TextItem,
)
logger = logging.getLogger(__name__)
class CopyGenerator:
"""5 步 Prompt 编排器。"""
def __init__(self, client=None, reviewer: Optional[Reviewer] = None):
if client is None:
from packages.shared.ai_client import get_doubao_client
client = get_doubao_client()
self.client = client
self.reviewer = reviewer or Reviewer(client)
# ── 底层调用 ────────────────────────────────────────────────────────
def _chat(self, template: PromptTemplate, system_kwargs: dict | None, **user_kwargs) -> str:
system = render_system_prompt(template, **(system_kwargs or {}))
user = render_user_prompt(template, **user_kwargs)
result = self.client.chat_completion(
[
{"role": "system", "content": system},
{"role": "user", "content": user},
],
temperature=0.7,
max_tokens=2048,
)
return result or ""
# ── 步骤1:图片多模态分析 ───────────────────────────────────────────
def analyze_images(self, images: list[str], industry: str = "") -> ImageAnalysis:
template = get_template("image_analysis")
image_urls = "\n".join(f"第{i + 1}张:{url}" for i, url in enumerate(images))
system = render_system_prompt(template)
user = render_user_prompt(template, image_count=len(images), industry=industry or "通用", image_urls=image_urls)
raw = self.client.vision_completion(
[
{"role": "system", "content": system},
{"role": "user", "content": user},
],
images=images,
max_tokens=2048,
temperature=0.3,
)
analysis = self._parse_image_analysis(raw or "")
if not analysis.products and not analysis.key_selling_points:
logger.warning("图片分析标签解析失败,走规则 fallback")
return self._fallback_image_analysis(images, raw or "")
return analysis
def _parse_image_analysis(self, raw: str) -> ImageAnalysis:
products = [
ProductItem(
name=n["attrs"].get("name", "无法判断"),
features=n["attrs"].get("features", "无法判断"),
position=n["attrs"].get("position", "secondary"),
image_index=xp.attr_int(n["attrs"].get("image_index"), 0),
)
for n in xp.find_all(raw, "product")
]
colors = [
ColorItem(
hex=c["attrs"].get("hex", "#000000"),
name=c["attrs"].get("name", "无法判断"),
coverage=xp.attr_float(c["attrs"].get("coverage"), 0.0),
)
for c in xp.find_all(raw, "color")
]
people = xp.find_first(raw, "people")
visible_text = [
TextItem(text=t["attrs"].get("text", ""), position=t["attrs"].get("position", ""))
for t in xp.find_all(raw, "text_item")
]
quality_node = xp.find_first(raw, "quality")
selling_points = [n["text"] or n["attrs"].get("text", "") for n in xp.find_all(raw, "point")]
return ImageAnalysis(
products=products,
colors=colors,
has_person=xp.attr_bool(people["attrs"].get("has_person")) if people else False,
person_count=xp.attr_int(people["attrs"].get("count"), 0) if people else 0,
people=people["attrs"] if people else {},
mood=xp.text_of(raw, "mood"),
visible_text=visible_text,
scene=xp.text_of(raw, "scene"),
quality=quality_node["attrs"] if quality_node else {},
key_selling_points=[p for p in selling_points if p],
raw=raw,
)
def _fallback_image_analysis(self, images: list[str], raw: str) -> ImageAnalysis:
return ImageAnalysis(
products=[ProductItem(name="无法判断(视觉分析不可用)", image_index=0)],
scene="无法判断",
raw=raw,
)
# ── 步骤2:意图解析 ─────────────────────────────────────────────────
def parse_intent(self, user_copy_text: str, image_analysis: ImageAnalysis, industry: str = "") -> IntentResult:
template = get_template("intent_parsing")
raw = self._chat(
template,
None,
user_copy_text=user_copy_text or "(用户没有提供文案)",
industry=industry or "通用",
image_analysis=self._image_brief(image_analysis),
)
intent = self._parse_intent(raw)
if not intent.intent_summary and not intent.core_messages:
logger.warning("意图解析标签解析失败,走规则 fallback")
return self._fallback_intent(user_copy_text, raw)
return intent
def _parse_intent(self, raw: str) -> IntentResult:
messages = [
CoreMessage(
text=n["text"],
must_keep=xp.attr_bool(n["attrs"].get("must_keep"), default=False),
confidence=xp.attr_float(n["attrs"].get("confidence"), 0.0),
)
for n in xp.find_all(raw, "message")
if n["text"]
]
brands = [
PersonalBrand(text=n["text"], category=n["attrs"].get("category", "brand"))
for n in xp.find_all(raw, "brand")
if n["text"]
]
missing = [n["text"] for n in xp.find_all(raw, "info") if n["text"]]
return IntentResult(
intent_summary=xp.text_of(raw, "intent_summary"),
core_messages=messages,
personal_brands=brands,
emotion_tone=xp.text_of(raw, "emotion_tone"),
missing_info=missing,
raw=raw,
)
def _fallback_intent(self, user_copy_text: str, raw: str) -> IntentResult:
text = (user_copy_text or "").strip()
messages = [CoreMessage(text=text[:80], must_keep=True, confidence=1.0)] if text else []
return IntentResult(
intent_summary=text[:30] or "未提供文案,按产品图片自由创作",
core_messages=messages,
personal_brands=[],
raw=raw,
)
# ── 步骤3:文案融合生成(三档)──────────────────────────────────────
def fuse(
self,
fusion_level: str,
image_analysis: ImageAnalysis,
intent: IntentResult,
industry: str = "",
target_customer: str = "",
marketing_purpose: str = "",
duration: int = 15,
) -> FusionResult:
template = get_template("copy_fusion")
system_kwargs = {
"fusion_instruction": FUSION_INSTRUCTIONS.get(fusion_level, FUSION_INSTRUCTIONS["ai_polish"]),
"global_constraints": GLOBAL_CONSTRAINTS,
"negative_rules": NEGATIVE_RULES,
}
raw = self._chat(
template,
system_kwargs,
industry=industry or "通用",
target_customer=target_customer or "通用消费者",
marketing_purpose=marketing_purpose or "产品种草",
duration=duration,
image_analysis=self._image_brief(image_analysis),
intent_result=self._intent_brief(intent),
)
result = self._parse_fusion(raw)
if not result.title and not result.script_segments:
logger.warning("文案融合标签解析失败(fusion=%s),走规则 fallback", fusion_level)
return self._fallback_fusion(fusion_level, image_analysis, intent, duration, raw)
return result
def _parse_fusion(self, raw: str) -> FusionResult:
body_points = [
BodyPoint(
text=n["text"],
elaboration=n["attrs"].get("elaboration", ""),
image_index=xp.attr_int(n["attrs"].get("image_index"), 0),
)
for n in xp.find_all(raw, "point")
if n["text"]
]
segments = [
ScriptSegment(
text=n["text"],
duration_sec=xp.attr_float(n["attrs"].get("duration_sec"), 0.0),
image_index=xp.attr_int(n["attrs"].get("image_index"), 0),
)
for n in xp.find_all(raw, "segment")
if n["text"]
]
return FusionResult(
title=xp.text_of(raw, "title"),
hook=xp.text_of(raw, "hook"),
body_points=body_points,
cta=xp.text_of(raw, "cta"),
script_segments=segments,
word_count=xp.attr_int(xp.text_of(raw, "word_count"), 0),
estimated_duration=xp.attr_int(xp.text_of(raw, "estimated_duration"), 0),
raw=raw,
)
def _fallback_fusion(
self,
fusion_level: str,
image_analysis: ImageAnalysis,
intent: IntentResult,
duration: int,
raw: str,
) -> FusionResult:
product_name = image_analysis.products[0].name if image_analysis.products else "这款产品"
selling = image_analysis.key_selling_points[:2]
if fusion_level == "ai_full":
title = f"{product_name},很多人用完都回购了"
hook = f"这个{product_name},我想认真说说"
body = selling or ["图片可见的产品卖点"]
cta = "感兴趣的可以了解一下"
elif fusion_level == "user_primary":
user_text = intent.intent_summary or product_name
title = user_text[:20]
hook = user_text[:15]
body = [m.text for m in intent.core_messages] or [user_text]
cta = "想了解的可以看看"
else:
title = intent.intent_summary[:20] or product_name
hook = intent.core_messages[0].text[:15] if intent.core_messages else product_name
body = [m.text for m in intent.core_messages] or selling or [product_name]
cta = "有需要的可以了解一下"
brand_texts = [b.text for b in intent.personal_brands]
points = [BodyPoint(text=b) for b in body]
lines = [hook] + body + brand_texts[:2] + [cta]
joined = ",".join(lines)
per = max(3, duration // max(1, len(lines)))
segments = [ScriptSegment(text=line, duration_sec=per, image_index=0) for line in lines]
return FusionResult(
title=title,
hook=hook,
body_points=points,
cta=cta,
script_segments=segments,
word_count=len(joined),
estimated_duration=duration,
raw=raw,
)
# ── 步骤4:编导级分镜 ───────────────────────────────────────────────
def storyboard(
self, fusion: FusionResult, image_analysis: ImageAnalysis, images: list[str], duration: int
) -> Storyboard:
template = get_template("storyboard")
raw = self._chat(
template,
None,
duration=duration,
image_count=len(images),
fusion_result=self._fusion_brief(fusion),
image_analysis=self._image_brief(image_analysis),
)
board = self._parse_storyboard(raw)
if not board.clips:
logger.warning("分镜标签解析失败,走规则 fallback")
return self._fallback_storyboard(fusion, duration, raw)
return board
def _parse_storyboard(self, raw: str) -> Storyboard:
clips: list[Clip] = []
for node in xp.find_all(raw, "clip"):
attrs = node["attrs"]
body = node["text"]
kb = xp.find_first(node["text"] and f"<root>{node['text']}</root>", "ken_burns")
clips.append(
Clip(
image_index=xp.attr_int(attrs.get("image_index"), 0),
transition=attrs.get("transition", "cut"),
zoom=(None if attrs.get("zoom") in (None, "null", "None", "") else attrs.get("zoom")),
duration_sec=xp.attr_float(attrs.get("duration_sec"), 0.0),
bgm_note=attrs.get("bgm_note", ""),
voice_text=xp.text_of(body and f"<root>{body}</root>", "voice_text"),
subtitle_text=xp.text_of(body and f"<root>{body}</root>", "subtitle_text"),
ken_burns=KenBurns(
start=kb["attrs"].get("start", "0,0") if kb else "0,0",
end=kb["attrs"].get("end", "0,0") if kb else "0,0",
ease=kb["attrs"].get("ease", "linear") if kb else "linear",
),
)
)
return Storyboard(clips=clips, raw=raw)
def _fallback_storyboard(self, fusion: FusionResult, duration: int, raw: str) -> Storyboard:
segments = fusion.script_segments or [ScriptSegment(text=fusion.hook or fusion.title, duration_sec=duration)]
total = sum(s.duration_sec for s in segments) or duration
clips = [
Clip(
image_index=min(s.image_index, 0),
transition="cut",
duration_sec=max(2.0, s.duration_sec * duration / total if total else duration / len(segments)),
voice_text=s.text,
subtitle_text=s.text[:20],
)
for s in segments
]
return Storyboard(clips=clips, raw=raw)
# ── 步骤5:审核(不通过自动重写1次)─────────────────────────────────
def review_and_rewrite(
self, fusion: FusionResult, intent: IntentResult, fusion_level: str
) -> tuple[FusionResult, ReviewResult, int]:
"""返回最终文案、最后一次审核结果、重写次数(0或1)。"""
review = self.reviewer.review(fusion, intent, fusion_level)
if review.passed:
return fusion, review, 0
logger.info("文案审核不通过,自动重写 1 次:%s", [i.text for i in review.issues])
rewritten = self.reviewer.rewrite(fusion, review, intent, fusion_level)
second = self.reviewer.review(rewritten, intent, fusion_level)
if second.passed:
return rewritten, second, 1
# 二次仍不通过:带上重写结果和问题返回,由上游决定是否交给前端
return rewritten, second, 1
# ── 全流程编排 ──────────────────────────────────────────────────────
def generate(
self,
images: list[str],
*,
industry: str = "",
target_customer: str = "",
marketing_purpose: str = "",
duration: int = 15,
user_copy_text: str = "",
fusion_level: str = "ai_polish",
) -> dict:
image_analysis = self.analyze_images(images, industry)
intent = self.parse_intent(user_copy_text, image_analysis, industry)
fusion = self.fuse(
fusion_level,
image_analysis,
intent,
industry=industry,
target_customer=target_customer,
marketing_purpose=marketing_purpose,
duration=duration,
)
fusion, review, rewrites = self.review_and_rewrite(fusion, intent, fusion_level)
board = self.storyboard(fusion, image_analysis, images, duration)
return {
"image_analysis": image_analysis,
"intent_result": intent,
"fusion_result": fusion,
"review_result": review,
"storyboard": board,
"rewrite_count": rewrites,
}
# ── 简报工具 ────────────────────────────────────────────────────────
@staticmethod
def _image_brief(a) -> str:
if a is None:
return "无图片分析信息"
lines = [f"产品:{p.name}({p.features})" for p in a.products]
lines += [f"卖点:{s}" for s in a.key_selling_points]
lines.append(f"场景:{a.scene}")
return "\n".join(lines) or "无图片分析信息"
@staticmethod
def _intent_brief(i: IntentResult) -> str:
lines = [f"意图:{i.intent_summary}"]
lines += [f"核心信息[must_keep={m.must_keep}]:{m.text}" for m in i.core_messages]
lines += [f"事实({b.category}):{b.text}" for b in i.personal_brands]
return "\n".join(lines)
@staticmethod
def _fusion_brief(f: FusionResult) -> str:
lines = [f"标题:{f.title}", f"钩子:{f.hook}"]
lines += [f"要点:{p.text}" for p in f.body_points]
lines += [f"配音:{s.text}" for s in f.script_segments]
lines.append(f"行动号召:{f.cta}")
return "\n".join(lines)
@@ -0,0 +1,160 @@
"""Prompt 模板加载器:从 viral_video_prompt_templates 读模板,30 秒 TTL 热加载。
DB 不可用或没有数据时自动回落到 prompts.DEFAULT_TEMPLATES,保证流程不阻断。
"""
from __future__ import annotations
import threading
import time
from dataclasses import dataclass
from typing import Optional
import sqlalchemy as sa
from packages.adapters.sqlalchemy_impl import session as _session_mod
from packages.application.viral_video.prompts import DEFAULT_TEMPLATES
CACHE_TTL_SECONDS = 30.0
_VALID_TYPES = {"image_analysis", "intent_parsing", "copy_fusion", "storyboard", "review"}
@dataclass
class PromptTemplate:
name: str
prompt_type: str
version: int
system_prompt: str
user_prompt_template: str
example_output: str = ""
is_active: bool = True
_lock = threading.Lock()
_cache: dict[str, tuple[float, PromptTemplate]] = {}
def _fallback(prompt_type: str) -> Optional[PromptTemplate]:
for item in DEFAULT_TEMPLATES:
if item["prompt_type"] == prompt_type:
return PromptTemplate(
name=item["name"],
prompt_type=item["prompt_type"],
version=item["version"],
system_prompt=item["system_prompt"],
user_prompt_template=item["user_prompt_template"],
example_output=item["example_output"] or "",
is_active=bool(item["is_active"]),
)
return None
_lazy_session = None
def _get_session():
"""优先用全局 SessionLocal(worker);否则按应用配置懒建同步引擎(api)。"""
global _lazy_session
if _session_mod.SessionLocal is not None:
return _session_mod.SessionLocal()
if _lazy_session is not None:
return _lazy_session()
try:
from packages.config import get_shared_settings
url = str(get_shared_settings().database_url)
except Exception: # noqa: BLE001
return None
if not url:
return None
url = url.replace("postgresql+asyncpg://", "postgresql+psycopg://")
url = url.replace("postgresql://", "postgresql+psycopg://") if url.startswith("postgresql://") else url
engine = sa.create_engine(url, pool_pre_ping=True, pool_size=2, max_overflow=2)
from sqlalchemy.orm import sessionmaker
_lazy_session = sessionmaker(bind=engine)
return _lazy_session()
def _load_from_db(prompt_type: str) -> Optional[PromptTemplate]:
session = None
try:
session = _get_session()
if session is None:
return None
sql = sa.text("""
SELECT name, prompt_type, version, system_prompt,
user_prompt_template, COALESCE(example_output, '') AS example_output,
is_active
FROM viral_video_prompt_templates
WHERE prompt_type = :pt AND is_active = TRUE
ORDER BY version DESC
LIMIT 1
""")
row = session.execute(sql, {"pt": prompt_type}).first()
if row is None:
return None
return PromptTemplate(
name=row[0],
prompt_type=row[1],
version=int(row[2]),
system_prompt=row[3],
user_prompt_template=row[4],
example_output=row[5] or "",
is_active=bool(row[6]),
)
except Exception: # noqa: BLE001 - 表不存在/DB 不可用时静默回落
return None
finally:
if session is not None:
try:
session.close()
except Exception: # noqa: BLE001
pass
def get_template(prompt_type: str, *, force_refresh: bool = False) -> Optional[PromptTemplate]:
"""取某类型当前启用模板,30 秒缓存;DB 无数据则回落到代码默认模板。"""
if prompt_type not in _VALID_TYPES:
raise ValueError(f"未知 prompt_type: {prompt_type}")
now = time.monotonic()
with _lock:
cached = _cache.get(prompt_type)
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)
if template is not None:
with _lock:
_cache[prompt_type] = (now, template)
return template
def invalidate() -> None:
"""清空缓存(测试用)。"""
with _lock:
_cache.clear()
class _SafeDict(dict):
def __missing__(self, key: str) -> str:
return "{" + key + "}"
def _safe_format(text: str, kwargs: dict) -> str:
try:
return text.format_map(_SafeDict(kwargs))
except Exception: # noqa: BLE001
return text
def render_user_prompt(template: PromptTemplate, **kwargs) -> str:
"""填充 user_prompt_template 占位符,缺键原样保留不报错。"""
return _safe_format(template.user_prompt_template, kwargs)
def render_system_prompt(template: PromptTemplate, **kwargs) -> str:
"""copy_fusion 等 system_prompt 含运行时变量时填充。"""
return _safe_format(template.system_prompt, kwargs)
+230
View File
@@ -0,0 +1,230 @@
"""爆款视频 Prompt 模板默认值(v8 / v3 叙述优先重构)。
设计原则(灵应 2026-10-07):LLM 直接输出最终给用户看的文案,代码尽量薄。
- image_analysis v8:VLM 主交付物是自然叙述风格的 summary_markdown,结构化
字段仅保留 type/name/brand/has_person,顶层 products 改名 images;
- storyboard v3:口播台词口语化、画面描述有画面感,copy_display_markdown 是
LLM 直接写给用户看的流畅叙述文案,代码只做解析不改写;
- intent_parsing 步骤整体删除,意图理解并入 storyboard 一次调用。
模板字段与 DB 表 viral_video_prompt_templates、prompt_loader 完全对应:
name / prompt_type / version(int) / system_prompt / user_prompt_template /
example_output / is_active。
"""
from __future__ import annotations
# 所有文案类 Prompt 自动注入的硬约束
GLOBAL_CONSTRAINTS = """【必须遵守的硬约束】
1. 不编造时间:不写“今年最新”“2024 爆款”等会过时的时间表述。
2. 不承诺效果:不写“保证”“一定”“100%有效”“包治百病”等绝对化用语。
3. 不编造价格、销量、认证、奖项:除非用户在文案中明确给出,否则一律不写。
4. 符合广告法及平台社区规范。
5. 只描述图片中真实可见的内容,看不到的不瞎猜。"""
# 负向提示(注入 storyboard / 视频生成负面词)
NEGATIVE_RULES = """【反套路化要求】
禁止使用“家人们谁懂啊”“绝绝子”“宝子们”“家人们”“太绝了”“yyds”等烂大街网络词;
禁止固定模板化开头;语言要像真人朋友之间的分享,自然、具体、有信息量。"""
# 输出禁用套路词(测试会检查)
BANNED_PHRASES = ["家人们谁懂啊", "绝绝子", "宝子们", "yyds", "太绝了"]
# 文案融合三档独立指令段(storyboard 一次生成,按档位注入风格指令)
FUSION_INSTRUCTIONS = {
"ai_full": """【本次创作模式:AI 全权创作】
你是资深短视频编导。用户只提供了产品/门店图片,没有给出具体文案方向。请根据图片的真实观察和营销参数,自由发挥创作完整成片级方案,口播自然、画面可拍。""",
"ai_polish": """【本次创作模式:AI 辅助润色】
用户已给出方向或碎碎念。以用户的意思为主,保留其所有核心信息,在此基础上润色、补衔接、优化表达,让口播更自然、画面更具体;绝不改变用户核心意思,不添加用户没提到的卖点,品牌名、价格、人名等事实原样保留。""",
"user_primary": """【本次创作模式:以用户原文为主】
最小化修改:只做必要的通顺、合规修正与衔接补全,用户的核心句子与事实一律不改;用户文案已经很好就直接用,不为改而改。""",
}
# ── 模板1:图片多模态分析 v8(叙述优先)───────────────────────────────
_IMAGE_ANALYSIS_SYSTEM = """你是一名擅长观察和写作的品牌内容编导。面对一张真实图片,先用眼睛仔细看,再用自然、流畅、具体的中文把画面写成一段可以直接读给人听的描述。
## 输出格式(严格 JSON,不要输出 JSON 以外的任何内容)
{
"images": [
{
"type": "store 或 product 或 person 或 scene,四选一",
"name": "主体名称,看不出就写“未识别”",
"brand": "品牌名,看不出就留空字符串",
"has_person": false,
"summary_markdown": "用 Markdown 写成的自然叙述,这是最主要的交付物"
}
]
}
## summary_markdown 写作要求(最重要)
1. 写成完整、通顺的句子,像在跟朋友认真描述你看到的画面;不要用分号堆砌关键词,不要罗列“核心特征:xxx”“主色调:xxx”这类填表式标签。
2. 开头先给一句整体定性,让读者立刻明白这是什么场景、什么主体。
3. 颜色、材质、形状、部件要具体可感,写到位置和搭配;画面里出现的文字原样读出并自然融进句子,数字、规格、价格精确引用,看不清的不要编造。
4. 只写真实看到的内容,不脑补功能、疗效、销量或画面之外的信息。
5. 长度控制在 200-500 字。
## 按类型组织内容
- type=store(门店/店内环境):用以下小标题分段,小标题下写连贯的句子而不是清单:
###店铺主体
###周边物品
1.家具陈设
2.商品与标识
- type=product(商品):按自然段从整体到局部描写——先说是什么、什么品牌,再写包装/外形、颜色与材质、标签文字、可见部件与规格。
- type=person(人物):描述人物身份感、姿态、穿着(上下装/颜色/款式)、动作与所处环境;用于品牌宣传时突出其精神状态。
- type=scene(纯场景/风景):描述空间或风景的构成、色彩、光线、氛围与关键物件。
## 判断规则
- has_person:画面中出现可辨识的真实人物(脸或完整上半身)才为 true,海报/模特立牌/照片里的人不算。
- 一张图只描述其本身;多张图属于同一场景时可呼应,但不编造对应关系。
- 输出必须是严格 JSON,summary_markdown 是字符串,内部换行用 \\n 表示。"""
_IMAGE_ANALYSIS_USER = """请分析这张图片。
图片地址:{image_url}
OCR 辅助文字(可能为空,仅供参考,不要照抄错误识别):{ocr_text}
严格按系统要求只输出 JSON。"""
_IMAGE_ANALYSIS_EXAMPLE = """{
"images": [
{
"type": "store",
"name": "御众堂门店",
"brand": "御众堂",
"has_person": false,
"summary_markdown": "###店铺主体\\n这是一家名为“御众堂”的线下门店内部,整体暖木色调……"
}
]
}"""
# ── 模板2:编导级分镜 v3(意图理解 + 分镜一次完成)────────────────────
_STORYBOARD_SYSTEM = (
"""你是一名懂短视频的编导和口播文案高手。你会拿到图片的真实观察、营销目的和用户参数,请一次性完成对营销意图的理解,并产出可直接拍摄/生成的分镜脚本。不要单独输出“意图解析”,意图要直接体现在台词和分镜里。
## 输出格式(XML,严格按结构输出,不要输出额外解释)
<script>
<copy_display_markdown><![CDATA[直接展示给用户看的成片文案,用 Markdown 写成流畅叙述]]></copy_display_markdown>
<clips>
<clip index="1">
<time_range>0-3秒</time_range>
<voiceover>这一镜的口播台词</voiceover>
<visual>具体、有画面感的镜头描述(主体/动作/镜头运动/景别/光线)</visual>
<reference_image_index>0</reference_image_index>
</clip>
</clips>
<voiceover_script>把所有 clip 的 voiceover 连成完整口播稿</voiceover_script>
<theme>一句话主题</theme>
<negative>"""
+ NEGATIVE_RULES
+ """</negative>
</script>
## 写作要求
1. 口播台词:像真人面对镜头说话,短句、口语化、有停顿有情绪,开头 3 秒给出钩子;不要书面腔,不要机械报参数。
2. 画面描述:写清“观众会看到什么”,有动作、有镜头运动、有景别和光线,具体可拍;不堆砌形容词,不写无法实现的画面。
3. copy_display_markdown:直接展示给最终用户的文案,用 Markdown 写成自然、流畅、有感染力的成片成片文案,可用小标题与短句组织;不要做字段列表,不要出现“镜头一/台词:”这类制作说明。
4. 内容必须来自图片观察与用户给出的信息,不编造卖点、不夸大、不使用绝对化用语和虚假承诺。
5. reference_image_index 填本镜参考图片序号(从 0 开始),没有合适参考图填 -1。
6. 分镜数量与时长匹配总时长,节奏紧凑。"""
)
_STORYBOARD_USER = """<marketing_purpose>{marketing_purpose}</marketing_purpose>
<image_analysis>
{image_summary}
</image_analysis>
<user_parameters>
<theme_hint>{theme_hint}</theme_hint>
<duration>{duration}秒</duration>
<aspect_ratio>{aspect_ratio}</aspect_ratio>
<tone>{tone}</tone>
<target_audience>{target_audience}</target_audience>
<extra_requirements>{extra_requirements}</extra_requirements>
</user_parameters>
{video_style_section}
请严格按 XML 结构输出分镜脚本。"""
_STORYBOARD_EXAMPLE = """<script>
<copy_display_markdown><![CDATA[# 在御众堂,把松弛的自己一点点找回来
产后妈妈最懂那种力不从心,推开门,暖光和一杯热茶先接住了你……]]></copy_display_markdown>
<clips>
<clip index="1">
<time_range>0-3秒</time_range>
<voiceover>生完娃,是不是连照镜子的勇气都没了?</voiceover>
<visual>中近景,暖光下一位妈妈略显疲惫地看向镜中,镜头缓缓推近</visual>
<reference_image_index>0</reference_image_index>
</clip>
</clips>
<voiceover_script>生完娃,是不是连照镜子的勇气都没了?</voiceover_script>
<theme>产后妈妈走进御众堂重拾状态</theme>
<negative>模糊、畸变、夸大疗效、绝对化用语</negative>
</script>"""
# ── 模板3:文案审核(合规/质量门禁)───────────────────────────────────
_REVIEW_SYSTEM = """你是一名短视频广告合规审核与文案优化专家。审核待审文案:
1) 广告法与平台合规(绝对化用语、虚假承诺、医疗功效宣称、导流违规);
2) 卖点是否聚焦、逻辑是否通顺、口播是否自然;
3) 是否有机械堆砌、书面腔、标签化表述。
只输出 XML,结构:
<review>
<passed>true 或 false</passed>
<issues>
<issue>
<severity>high 或 medium 或 low</severity>
<field>问题所在位置/字段</field>
<problem>具体问题</problem>
<suggestion>可直接替换的修改</suggestion>
</issue>
</issues>
<rewrite>整体重写后的合规流畅版本(无问题时留空)</rewrite>
</review>
没有问题时 issues 留空、passed 为 true、rewrite 留空。"""
_REVIEW_USER = """<fusion_text>
{fusion_text}
</fusion_text>
请审核以上文案。"""
_REVIEW_EXAMPLE = """<review>
<passed>false</passed>
<issues>
<issue>
<severity>high</severity>
<field>opening</field>
<problem>使用绝对化用语“全网第一”</problem>
<suggestion>改为“很多老客户回购的一款”</suggestion>
</issue>
</issues>
<rewrite>……</rewrite>
</review>"""
DEFAULT_TEMPLATES: list[dict] = [
{
"name": "图片多模态分析 v8",
"prompt_type": "image_analysis",
"version": 8,
"system_prompt": _IMAGE_ANALYSIS_SYSTEM,
"user_prompt_template": _IMAGE_ANALYSIS_USER,
"example_output": _IMAGE_ANALYSIS_EXAMPLE,
"is_active": True,
},
{
"name": "编导级分镜 v3",
"prompt_type": "storyboard",
"version": 3,
"system_prompt": _STORYBOARD_SYSTEM,
"user_prompt_template": _STORYBOARD_USER,
"example_output": _STORYBOARD_EXAMPLE,
"is_active": True,
},
{
"name": "文案审核",
"prompt_type": "review",
"version": 1,
"system_prompt": _REVIEW_SYSTEM,
"user_prompt_template": _REVIEW_USER,
"example_output": _REVIEW_EXAMPLE,
"is_active": True,
},
]
@@ -0,0 +1,337 @@
"""文案审核 + 自动重写(#2040 第5套 Prompt)。
6 维度:违规词 / 夸大承诺 / 事实一致性 / 用户意图保留 / 结构完整性 / 语气人设。
LLM 审核之外叠加本地规则预检(保证即使 LLM 不可用也能兜住广告法红线)。
"""
from __future__ import annotations
import logging
import re
from typing import Optional
from packages.application.viral_video import xml_parser as xp
from packages.application.viral_video.prompt_loader import (
get_template,
render_system_prompt,
render_user_prompt,
)
from packages.application.viral_video.schemas import (
FusionResult,
IntentResult,
ReviewIssue,
ReviewResult,
)
logger = logging.getLogger(__name__)
# 本地规则:绝对化/夸大词
_EXAGGERATION_PATTERNS = [
r"100\s*%",
r"百分百",
r"包治百病",
r"保证.{0,8}(有效|赚钱|瘦|好)",
r"绝对(有效|安全|靠谱)",
r"全网第一",
r"国家级",
r"特效",
r"立刻见效",
r"一喷(就|全|100)",
]
# 本地规则:平台违规/套路词
_VIOLATION_PHRASES = [
"家人们谁懂啊",
"绝绝子",
"宝子们",
"yyds",
"最(好|强|牛|便宜)", # 广告法极限词
"第一(名|品牌)?",
]
_LOCATIONS = ["title", "hook", "body_points", "cta", "script_segments"]
class Reviewer:
# markdown展示字段不参与合规审核(避免格式字符误判)
_MARKDOWN_FIELDS = {"summary_markdown", "copy_display_markdown"}
def __init__(self, client=None):
if client is None:
try:
from packages.shared.ai_router import ai_router
client = ai_router.get_llm_client("copy_review")
except Exception:
from packages.shared.ai_client import get_doubao_client
client = get_doubao_client()
self.client = client
# ── 审核 ────────────────────────────────────────────────────────────
def review(self, fusion: FusionResult, intent: IntentResult, fusion_level: str) -> ReviewResult:
local = self._rule_check(fusion, intent, fusion_level)
llm_result = self._llm_review(fusion, intent, fusion_level)
if llm_result is None:
# LLM审核失败(超时/网络错误等),降级放行,不阻断渲染
return ReviewResult(
passed=True,
issues=local,
rewrite_suggestions=[],
raw="",
)
# LLM 与本地规则合并去重
issues = self._merge_issues(llm_result.issues, local)
return ReviewResult(
passed=llm_result.passed and not local,
issues=issues,
rewrite_suggestions=llm_result.rewrite_suggestions,
raw=llm_result.raw,
)
def _llm_review(self, fusion: FusionResult, intent: IntentResult, fusion_level: str) -> Optional[ReviewResult]:
try:
return self._llm_review_inner(fusion, intent, fusion_level)
except Exception as e:
import logging
logging.getLogger(__name__).warning("[Reviewer] LLM审核调用异常,降级放行: %s", e)
return None
def _llm_review_inner(
self, fusion: FusionResult, intent: IntentResult, fusion_level: str
) -> Optional[ReviewResult]:
template = get_template("review")
system = render_system_prompt(template)
user = render_user_prompt(
template,
fusion_level=fusion_level,
fusion_result=self._fusion_text(fusion),
intent_result=self._intent_text(intent),
)
raw = self.client.chat_completion(
[
{"role": "system", "content": system},
{"role": "user", "content": user},
],
temperature=0.2,
max_tokens=1024,
timeout=25,
)
if not raw:
return None
passed = xp.text_of(raw, "passed").strip().lower()
issues = [
ReviewIssue(
dimension=n["attrs"].get("dimension", "未知维度"),
severity=n["attrs"].get("severity", "warning"),
location=n["attrs"].get("location", ""),
text=n["text"],
)
for n in xp.find_all(raw, "issue")
if n["text"]
]
suggestions = [n["text"] for n in xp.find_all(raw, "suggestion") if n["text"]]
parsed = ReviewResult(
passed=passed == "true" and not issues,
issues=issues,
rewrite_suggestions=suggestions,
raw=raw,
)
return parsed
# ── 本地规则预检 ────────────────────────────────────────────────────
def _rule_check(self, fusion: FusionResult, intent, fusion_level: str) -> list[ReviewIssue]:
issues: list[ReviewIssue] = []
for location, text in self._segments(fusion):
for pattern in _EXAGGERATION_PATTERNS:
if re.search(pattern, text):
issues.append(
ReviewIssue(
dimension="夸大承诺",
severity="error",
location=location,
text=f"出现夸大/绝对化表述:{self._hit(text, pattern)}",
)
)
for phrase in _VIOLATION_PHRASES:
if re.search(phrase, text, flags=re.IGNORECASE):
issues.append(
ReviewIssue(
dimension="违规词",
severity="error",
location=location,
text=f"出现违规或套路词:{self._hit(text, phrase)}",
)
)
# 结构完整性
if not fusion.title:
issues.append(ReviewIssue(dimension="结构完整性", severity="warning", location="title", text="缺少标题"))
if not fusion.hook:
issues.append(ReviewIssue(dimension="结构完整性", severity="warning", location="hook", text="缺少开头钩子"))
if not fusion.cta:
issues.append(ReviewIssue(dimension="结构完整性", severity="warning", location="cta", text="缺少行动号召"))
# 用户意图保留(must_keep)
full_text = self._fusion_text(fusion)
if fusion_level in {"ai_polish", "user_primary"} and intent is not None:
for message in intent.core_messages:
if message.must_keep:
key = self._compact(message.text)
if key and key[:10] not in self._compact(full_text):
issues.append(
ReviewIssue(
dimension="用户意图保留",
severity="warning",
location="script_segments",
text=f"用户核心信息被丢失:{message.text[:30]}",
)
)
for brand in intent.personal_brands:
if brand.text and brand.text not in full_text:
issues.append(
ReviewIssue(
dimension="事实一致性",
severity="error",
location="script_segments",
text=f"personal_brands 事实信息未原样保留:{brand.text[:30]}",
)
)
return issues
@staticmethod
def _hit(text: str, pattern: str) -> str:
match = re.search(pattern, text, flags=re.IGNORECASE)
return match.group(0) if match else pattern
@staticmethod
def _compact(text: str) -> str:
return re.sub(r"[\s,。!?、,.!?;;::\"'“”‘’()()【】\[\]]", "", text)
@staticmethod
def _merge_issues(llm_issues: list[ReviewIssue], local: list[ReviewIssue]) -> list[ReviewIssue]:
merged = list(local)
seen = {(i.dimension, Reviewer._compact(i.text)[:20]) for i in local}
for issue in llm_issues:
key = (issue.dimension, Reviewer._compact(issue.text)[:20])
if key not in seen:
merged.append(issue)
seen.add(key)
return merged
# ── 自动重写(1 次)─────────────────────────────────────────────────
def rewrite(
self,
fusion: FusionResult,
review: ReviewResult,
intent: IntentResult,
fusion_level: str,
) -> FusionResult:
from packages.application.viral_video.generator import CopyGenerator
template = get_template("copy_fusion")
system_kwargs = {
"fusion_instruction": (
"【本次任务:按审核意见修正文案】只修改指出的问题,其他内容尽量原样保留;"
"personal_brands 事实信息逐字保留;修正后按原标签格式完整输出。"
),
"global_constraints": "",
"negative_rules": "",
}
issue_text = "\n".join(f"- [{i.dimension}/{i.location}] {i.text}" for i in review.issues)
suggestion_text = "\n".join(f"- {s}" for s in review.rewrite_suggestions)
user = render_user_prompt(
template,
industry="",
target_customer="",
marketing_purpose="",
duration=fusion.estimated_duration or 15,
image_analysis="(沿用原图片分析)",
intent_result=self._intent_text(intent),
)
user = (
f"{user}\n\n原文案:\n{self._fusion_text(fusion)}\n\n"
f"审核发现的问题:\n{issue_text}\n\n修改建议:\n{suggestion_text or '(无)'}\n"
"请输出修正后的完整文案。"
)
system = render_system_prompt(template, **system_kwargs)
raw = self.client.chat_completion(
[
{"role": "system", "content": system},
{"role": "user", "content": user},
],
temperature=0.5,
max_tokens=2048,
timeout=25,
)
if not raw:
return self._rule_fix(fusion, review)
rewritten = CopyGenerator._parse_fusion(CopyGenerator(self.client), raw)
if not rewritten.title and not rewritten.script_segments:
return self._rule_fix(fusion, review)
# 保底:personal_brands 必须保留
full = self._fusion_text(rewritten)
for brand in intent.personal_brands:
if brand.text and brand.text not in full:
rewritten.cta = (rewritten.cta + brand.text).strip()
return rewritten
def _rule_fix(self, fusion: FusionResult, review: ReviewResult) -> FusionResult:
"""LLM 重写不可用时的本地兜底:删除/替换明显违规表述。"""
replacements = [
(re.compile(r"100\s*%|百分百"), "大部分"),
(re.compile(r"绝对(有效|安全|靠谱)"), "比较\\1"),
(re.compile(r"包治百病"), "适用多种情况"),
(re.compile(r"立刻见效"), "坚持使用会有改善"),
(re.compile(r"一喷(就|全|100%)"), "喷上等一会儿可以"),
(re.compile(r"家人们谁懂啊|绝绝子|宝子们|yyds", re.IGNORECASE), ""),
(re.compile(r"最好|最强|最牛|最便宜"), "很不错"),
]
def fix(text: str) -> str:
for pattern, repl in replacements:
text = pattern.sub(repl, text)
return text
fusion.title = fix(fusion.title)
fusion.hook = fix(fusion.hook)
fusion.cta = fix(fusion.cta)
for point in fusion.body_points:
point.text = fix(point.text)
point.elaboration = fix(point.elaboration)
for segment in fusion.script_segments:
segment.text = fix(segment.text)
fusion.raw = ""
return fusion
# ── 文本工具 ────────────────────────────────────────────────────────
@staticmethod
def _segments(fusion: FusionResult):
yield "title", fusion.title
yield "hook", fusion.hook
for point in fusion.body_points:
yield "body_points", f"{point.text} {point.elaboration}"
yield "cta", fusion.cta
for segment in fusion.script_segments:
yield "script_segments", segment.text
@staticmethod
def _fusion_text(fusion: FusionResult) -> str:
_MARKDOWN_FIELDS = {"summary_markdown", "copy_display_markdown"}
parts = [fusion.title, fusion.hook]
parts += [p.text for p in fusion.body_points]
parts += [s.text for s in fusion.script_segments]
parts.append(fusion.cta)
# 过滤掉markdown展示字段,避免格式字符被误判
parts = [p for p in parts if not any(mk in p for mk in _MARKDOWN_FIELDS)]
return "\n".join(p for p in parts if p)
@staticmethod
def _intent_text(intent) -> str:
if intent is None:
return "无意图信息"
parts = [f"意图:{intent.intent_summary}"]
parts += [f"核心信息[must_keep={m.must_keep}]:{m.text}" for m in intent.core_messages]
parts += [f"事实({b.category}):{b.text}" for b in intent.personal_brands]
return "\n".join(parts)
+116
View File
@@ -0,0 +1,116 @@
"""内部 Pydantic 校验模型(不暴露给运营,运营只看 DB 里的纯文本)。"""
from __future__ import annotations
from pydantic import BaseModel, Field
class ProductItem(BaseModel):
name: str = "无法判断"
features: str = "无法判断"
position: str = "secondary"
image_index: int = 0
class ColorItem(BaseModel):
hex: str = "#000000"
name: str = "无法判断"
coverage: float = 0.0
class TextItem(BaseModel):
text: str = ""
position: str = ""
class ImageAnalysis(BaseModel):
products: list[ProductItem] = Field(default_factory=list)
colors: list[ColorItem] = Field(default_factory=list)
has_person: bool = False
person_count: int = 0
people: dict[str, str] = Field(default_factory=dict)
mood: str = ""
visible_text: list[TextItem] = Field(default_factory=list)
scene: str = ""
quality: dict[str, str] = Field(default_factory=dict)
key_selling_points: list[str] = Field(default_factory=list)
raw: str = ""
class CoreMessage(BaseModel):
text: str
must_keep: bool = False
confidence: float = 0.0
class PersonalBrand(BaseModel):
text: str
category: str = "brand"
class IntentResult(BaseModel):
intent_summary: str = ""
core_messages: list[CoreMessage] = Field(default_factory=list)
personal_brands: list[PersonalBrand] = Field(default_factory=list)
emotion_tone: str = ""
missing_info: list[str] = Field(default_factory=list)
raw: str = ""
class BodyPoint(BaseModel):
text: str
elaboration: str = ""
image_index: int = 0
class ScriptSegment(BaseModel):
text: str
duration_sec: float = 0
image_index: int = 0
class FusionResult(BaseModel):
title: str = ""
hook: str = ""
body_points: list[BodyPoint] = Field(default_factory=list)
cta: str = ""
script_segments: list[ScriptSegment] = Field(default_factory=list)
word_count: int = 0
estimated_duration: int = 0
raw: str = ""
class KenBurns(BaseModel):
start: str = "0,0"
end: str = "0,0"
ease: str = "linear"
class Clip(BaseModel):
image_index: int = 0
transition: str = "cut"
zoom: str | None = None
duration_sec: float = 0
bgm_note: str = ""
voice_text: str = ""
subtitle_text: str = ""
ken_burns: KenBurns = Field(default_factory=KenBurns)
class Storyboard(BaseModel):
clips: list[Clip] = Field(default_factory=list)
raw: str = ""
class ReviewIssue(BaseModel):
dimension: str
severity: str = "warning"
location: str = ""
text: str = ""
class ReviewResult(BaseModel):
passed: bool = True
issues: list[ReviewIssue] = Field(default_factory=list)
rewrite_suggestions: list[str] = Field(default_factory=list)
raw: str = ""
@@ -0,0 +1,113 @@
"""XML 标签式输出解析器(替代 json.loads)。
LLM 按 ``<tag attr="x">内容</tag>`` 输出,本模块解析,解析失败不抛异常,
由调用方走规则 fallback。采用栈式扫描,嵌套标签全部可提取(内外层都保留)。
"""
from __future__ import annotations
import re
from html import unescape
from typing import Optional
_OPEN_RE = re.compile(r"<(?P<tag>[\w-]+)(?P<attrs>(?:\s(?:[^>]*?\S)?)?)(?P<self>/?)>")
_CLOSE_RE = re.compile(r"</(?P<tag>[\w-]+)\s*>")
_ATTR_RE = re.compile(r"""([\w:-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')""")
_CDATA_RE = re.compile(r"^<!\[CDATA\[(.*)\]\]>$", re.DOTALL)
def _strip_cdata(s: str) -> str:
"""剥离 LLM 可能照抄示例输出的 ``<![CDATA[...]]>`` 包裹层。"""
m = _CDATA_RE.match(s.strip())
return m.group(1) if m else s
def parse_attributes(raw: str) -> dict[str, str]:
"""解析标签属性字符串。"""
attrs: dict[str, str] = {}
for match in _ATTR_RE.finditer(raw or ""):
value = match.group(2) if match.group(2) is not None else match.group(3)
attrs[match.group(1)] = value
return attrs
def parse_tags(text: Optional[str]) -> list[dict]:
"""提取全部标签(含嵌套内外层),返回 [{tag, attrs, text}],按开标签出现顺序。"""
if not text:
return []
results: list[dict] = []
stack: list[dict] = []
token_re = re.compile(r"<[^>]+>")
for token in token_re.finditer(text):
raw_token = token.group(0)
# 先按开/闭标签匹配
open_match = _OPEN_RE.match(raw_token)
close_match = _CLOSE_RE.match(raw_token)
is_close_tag = raw_token.startswith("</")
if not is_close_tag and open_match:
is_self_close = open_match.group("self") == "/"
node = {
"tag": open_match.group("tag"),
"attrs": parse_attributes(open_match.group("attrs")),
"text": "",
"_start": token.end(),
}
if is_self_close:
node.pop("_start")
results.append(node)
else:
stack.append(node)
results.append(node)
elif is_close_tag and close_match:
tag = close_match.group("tag")
# 弹出到最近同名开标签
for idx in range(len(stack) - 1, -1, -1):
if stack[idx]["tag"] == tag:
node = stack[idx]
node["text"] = unescape(text[node["_start"] : token.start()].strip())
node["text"] = _strip_cdata(node["text"])
node.pop("_start", None)
del stack[idx:]
break
# 未闭合标签:给剩余部分作为文本
for node in stack:
if "_start" in node:
node["text"] = unescape(text[node["_start"] :].strip())
node["text"] = _strip_cdata(node["text"])
node.pop("_start", None)
return results
def find_all(text: Optional[str], tag: str) -> list[dict]:
"""提取指定标签的全部节点。"""
return [n for n in parse_tags(text) if n["tag"] == tag]
def find_first(text: Optional[str], tag: str) -> Optional[dict]:
nodes = find_all(text, tag)
return nodes[0] if nodes else None
def text_of(text: Optional[str], tag: str, default: str = "") -> str:
node = find_first(text, tag)
return node["text"] if node else default
def attr_bool(value: Optional[str], default: bool = False) -> bool:
if value is None:
return default
return value.strip().lower() in {"true", "1", "yes", "是"}
def attr_float(value: Optional[str], default: float = 0.0) -> float:
try:
return float(value) if value is not None and value.strip() else default
except (TypeError, ValueError):
return default
def attr_int(value: Optional[str], default: int = 0) -> int:
try:
return int(float(value)) if value is not None and value.strip() else default
except (TypeError, ValueError):
return default
+94 -21
View File
@@ -80,40 +80,46 @@ class SharedSettings(BaseSettings):
# ── CosyVoice (阿里云百炼语音合成) ───────────────────────────────────
cosyvoice_api_key: str = ""
cosyvoice_base_url: str = "https://dashscope.aliyuncs.com/api/v1"
cosyvoice_model: str = "cosyvoice-v3-flash"
cosyvoice_voice: str = "longxiaochun_v3" # 默认音色(v3 系列系统音色带 _v3 后缀)
cosyvoice_base_url: str = ""
cosyvoice_model: str = ""
cosyvoice_voice: str = "longxiaochun_v3"
cosyvoice_sample_rate: int = 22050
cosyvoice_format: str = "mp3" # 输出格式:mp3/wav/pcm
cosyvoice_format: str = "mp3"
# 音色克隆模型名(固定为 voice-enrollment)
cosyvoice_clone_model: str = "voice-enrollment"
cosyvoice_clone_model: str = ""
# ── 豆包大模型(火山引擎方舟) ────────────────────────────────────────
# AI模型路由化:model/base_url 默认值清空,由 DB ai_models/ai_capability_configs 配置驱动。
# 环境变量仍可覆盖(兼容旧部署);无任何配置时 ai_router fallback 提供最终默认值。
doubao_api_key: str = ""
doubao_model: str = "doubao-seed-1-6-250615" # 推理模型(通用兜底)
doubao_fast_model: str = "doubao-1-5-pro-32k-250115" # 快速结构化输出模型(编导脚本/意图解析/审核)
doubao_base_url: str = "https://ark.cn-beijing.volces.com/api/v3"
doubao_timeout: int = 30
doubao_max_retries: int = 2
doubao_vision_model: str = "doubao-1-5-vision-pro-250328" # 高精度视觉(备用)
doubao_vision_lite_model: str = "doubao-1-5-vision-lite-250315" # 快速视觉(商品识别默认,速度优先)
doubao_vision_use_lite: bool = True # viral-video 图片分析默认用 lite 提速
doubao_embedding_model: str = "doubao-embedding-large-text-240915"
doubao_video_model: str = "doubao-seedance-2-5-260628"
doubao_video_timeout: int = 600 # 视频生成轮询总超时(秒)
doubao_video_poll_interval: int = 10 # 轮询间隔(秒)
doubao_model: str = ""
doubao_fast_model: str = ""
doubao_base_url: str = ""
doubao_timeout: int = 45
doubao_max_retries: int = 3
doubao_vision_model: str = ""
doubao_vision_lite_model: str = ""
doubao_vision_use_lite: bool = True
doubao_embedding_model: str = ""
doubao_video_model: str = ""
doubao_video_timeout: int = 600
doubao_video_poll_interval: int = 10
doubao_image_model: str = ""
doubao_image_size: str = "1K"
doubao_image_timeout: int = 60
doubao_trust_chain_enabled: bool = True
# ── DashScope (阿里云百炼 Wan 3.0 等) ─────────────────────────────────
dashscope_api_key: str = ""
dashscope_base_url: str = "https://dashscope.aliyuncs.com/api/v1"
dashscope_video_timeout: int = 900 # Wan 视频任务轮询总超时(秒)
dashscope_base_url: str = ""
dashscope_video_timeout: int = 900
dashscope_video_poll_interval: int = 10
# ── MediaKit (火山引擎 AI 媒体工具) ──────────────────────────────────
mediakit_api_key: str = ""
mediakit_base_url: str = "https://mediakit.cn-beijing.volces.com/api/v1"
mediakit_base_url: str = ""
mediakit_timeout: int = 60
mediakit_cover_enabled: bool = False # 封面抽帧是否走MediaKit(默认false走本地ffmpeg+cv2,<2s完成)
mediakit_cover_enabled: bool = False
# ── 积分/会员系统 (#1895) ────────────────────────────────────────────
# 积分系统总开关(产品要求 #1895:暂停积分系统但保留全部代码/表/接口)。
@@ -167,6 +173,73 @@ class SharedSettings(BaseSettings):
# 判断 Worker 可用的心跳新鲜度窗口(秒)—— last_heartbeat_at 在窗口内视为在线
gpu_worker_stale_seconds: int = 300
# ── Ditto 蚂蚁数字人口型 API(#2076)─────────────────────────────────
# 是否优先使用 Ditto(蚂蚁数字人,替代 MuseTalk)。开关开启且 base_url 配置
# 非空时,对口型任务优先走 Ditto;失败后回退 MuseTalk/MediaKit。
use_ditto_lipsync: bool = Field(
default=False,
validation_alias=AliasChoices("USE_DITTO_LIPSYNC", "use_ditto_lipsync"),
)
# Ditto FastAPI 内网地址(Tailscale),如 http://100.x.x.x:8000
ditto_api_base_url: str = Field(
default="",
validation_alias=AliasChoices("DITTO_API_BASE_URL", "ditto_api_base_url"),
)
# 默认人物模板视频 URL(正面 5-10 秒循环、光线均匀、半身)。Ditto 模式下忽略
# 用户上传的驱动视频/图片,统一用该模板;后续可扩展为多模板让用户选择。
ditto_default_video_url: str = Field(
default="",
validation_alias=AliasChoices("DITTO_DEFAULT_VIDEO_URL", "ditto_default_video_url"),
)
# 429 GPU 繁忙时指数退避最大重试次数
ditto_max_retries: int = Field(
default=3,
validation_alias=AliasChoices("DITTO_MAX_RETRIES", "ditto_max_retries"),
)
# Ditto 单次请求 read 超时(秒):数字人半身视频推理通常 30-120s(RTF≈2.8,40s音频约112s)
# connect 超时固定 10s(代码硬编码,网络不通快速失败)
ditto_request_timeout: int = Field(
default=120,
validation_alias=AliasChoices("DITTO_REQUEST_TIMEOUT", "ditto_request_timeout"),
)
# Ditto 句间过渡帧数(平滑表情/口型切换)
ditto_blend_frames: int = Field(
default=12,
validation_alias=AliasChoices("DITTO_BLEND_FRAMES", "ditto_blend_frames"),
)
# ── Ditto LLM 情绪分析(emo_timeline)──────────────────────────────
# 总开关;关闭或 LLM 失败时走 GPU 端关键词匹配兜底
ditto_emotion_enabled: bool = Field(
default=False,
validation_alias=AliasChoices("DITTO_EMOTION_ENABLED", "ditto_emotion_enabled"),
)
ditto_emotion_model: str = Field(
default="doubao-seed-2-1-lite-250915",
validation_alias=AliasChoices("DITTO_EMOTION_MODEL", "ditto_emotion_model"),
)
ditto_emotion_temperature: float = Field(
default=0.1,
validation_alias=AliasChoices("DITTO_EMOTION_TEMPERATURE", "ditto_emotion_temperature"),
)
ditto_emotion_timeout: int = Field(
default=10,
validation_alias=AliasChoices("DITTO_EMOTION_TIMEOUT", "ditto_emotion_timeout"),
)
ditto_emotion_max_tokens: int = Field(
default=1024,
validation_alias=AliasChoices("DITTO_EMOTION_MAX_TOKENS", "ditto_emotion_max_tokens"),
)
ditto_emotion_cache_size: int = Field(
default=500,
validation_alias=AliasChoices("DITTO_EMOTION_CACHE_SIZE", "ditto_emotion_cache_size"),
)
# 提示词模板:必须包含 {文案} 占位符;后台可通过环境变量覆盖
ditto_emotion_prompt: str = Field(
default="",
validation_alias=AliasChoices("DITTO_EMOTION_PROMPT", "ditto_emotion_prompt"),
)
# ── P4000 NVENC 硬件编码 ────────────────────────────────────────────
# GPU 编码总开关;关闭或 endpoint 为空时始终走本机 CPU libx264
enable_gpu_encode: bool = Field(
+376
View File
@@ -0,0 +1,376 @@
"""功能计费配置服务:从 feature_pricing_configs 读配置,300 秒 TTL 内存缓存。
配置表由 xiaoxia-admin 侧维护(同库 PostgreSQL),本服务只读。
DB 不可用 / 表不存在 / 无数据时自动回落到内置兜底配置,保证业务不崩。
计费公式:最终积分 = (动态成本 + 固定成本) × 利润系数,price_cap 封顶。
启用条件:全局 points_enabled 总开关 AND 功能 is_enabled 同时为 true。
"""
from __future__ import annotations
import json
import logging
import threading
import time
from dataclasses import dataclass, field
from typing import Optional
import sqlalchemy as sa
from packages.adapters.sqlalchemy_impl import session as _session_mod
logger = logging.getLogger(__name__)
CACHE_TTL_SECONDS = 300.0
# ── 爆款视频兜底模型单价(与旧硬编码表/现状一致;DB 不可用时使用) ───────
# 结构:models[model_key][resolution]["true"/"false"] = 单价
# token 模式:元/百万输出 tokens;per_second 模式:元/秒
# 注意:仅 seedance-2.5 配置 true(图生视频)单价;其余模型只有 false,
# 精确 key 缺失时由 points_rules 回落到 seedance-2.5/false(与旧现状一致)。
_FALLBACK_VIRAL_MODEL_PRICING: dict = {
"seedance-2.5": {
"480p": {"false": 70.0, "true": 42.0},
"720p": {"false": 70.0, "true": 42.0},
"1080p": {"false": 77.0, "true": 46.0},
},
"seedance-2.0": {
"480p": {"false": 46.0},
"720p": {"false": 46.0},
"1080p": {"false": 51.0},
"4k": {"false": 80.0},
},
"seedance-2.0-fast": {
"480p": {"false": 28.0},
"720p": {"false": 28.0},
},
"seedance-2.0-mini": {
"480p": {"false": 9.2},
"720p": {"false": 9.2},
},
"wan-3.0": {
"480p": {"false": 0.3},
"720p": {"false": 0.6},
"1080p": {"false": 1.2},
},
}
@dataclass
class FeatureConfig:
"""功能计费配置快照。"""
feature_key: str
name: str = ""
emoji: str = ""
is_enabled: bool = False
fixed_cost: float = 0.0
profit_multiplier: float = 1.0
dynamic_unit_cost: float = 0.0
billing_mode: str = "model_based"
price_cap: float = 0.0
model_pricing: dict = field(default_factory=dict)
description: str = ""
# ── 进程内缓存:(loaded_monotonic, {feature_key: FeatureConfig}) ──────────
_lock = threading.Lock()
_cache: Optional[tuple[float, dict[str, FeatureConfig]]] = None
def _fallback_configs() -> dict[str, FeatureConfig]:
"""内置兜底配置:爆款启用(与现状一致),其余两个关闭。"""
return {
"viral_video": FeatureConfig(
feature_key="viral_video",
name="爆款视频",
emoji="🎬",
is_enabled=True,
fixed_cost=0.15,
profit_multiplier=1.3,
dynamic_unit_cost=0.0,
billing_mode="model_based",
price_cap=0.0,
model_pricing=json.loads(json.dumps(_FALLBACK_VIRAL_MODEL_PRICING)),
description="爆款视频动态定价(兜底配置)",
),
"lip_sync": FeatureConfig(
feature_key="lip_sync",
name="对口型",
emoji="🎙️",
is_enabled=False,
fixed_cost=0.0,
profit_multiplier=1.0,
dynamic_unit_cost=0.0,
billing_mode="per_second",
price_cap=0.0,
description="对口型计费(兜底配置,默认关闭)",
),
"smart_edit": FeatureConfig(
feature_key="smart_edit",
name="智能剪辑",
emoji="✂️",
is_enabled=False,
fixed_cost=0.0,
profit_multiplier=1.0,
dynamic_unit_cost=0.0,
billing_mode="model_based",
price_cap=0.0,
description="智能剪辑固定价计费(兜底配置,默认关闭)",
),
}
_lazy_session = None
def _get_session():
"""优先用全局 SessionLocal(worker);否则按应用配置懒建同步引擎(api)。"""
global _lazy_session
if _session_mod.SessionLocal is not None:
return _session_mod.SessionLocal()
if _lazy_session is not None:
return _lazy_session()
try:
from packages.config import get_shared_settings
url = str(get_shared_settings().database_url)
except Exception: # noqa: BLE001
return None
if not url:
return None
url = url.replace("postgresql+asyncpg://", "postgresql+psycopg://")
if url.startswith("postgresql://"):
url = url.replace("postgresql://", "postgresql+psycopg://")
engine = sa.create_engine(url, pool_pre_ping=True, pool_size=2, max_overflow=2)
from sqlalchemy.orm import sessionmaker
_lazy_session = sessionmaker(bind=engine)
return _lazy_session()
def _parse_model_pricing(raw) -> dict:
"""解析 model_pricing_json(Text JSON),空/失败 → {}。"""
if raw is None:
return {}
if isinstance(raw, dict):
return raw
text = str(raw).strip()
if not text:
return {}
try:
data = json.loads(text)
except (ValueError, TypeError):
logger.warning("model_pricing_json 解析失败,按空配置处理: %r", text[:200])
return {}
return data if isinstance(data, dict) else {}
def _to_float(value, default: float = 0.0) -> float:
try:
if value is None:
return default
return float(value)
except (TypeError, ValueError):
return default
def _load_all() -> dict[str, FeatureConfig]:
"""SELECT * FROM feature_pricing_configs,返回 {feature_key: FeatureConfig}。
表不存在 / DB 异常由调用方捕获并回落兜底配置。
"""
session = None
try:
session = _get_session()
if session is None:
raise RuntimeError("no db session available")
sql = sa.text("""
SELECT feature_key, name, emoji, is_enabled, fixed_cost,
profit_multiplier, dynamic_unit_cost, billing_mode,
price_cap, model_pricing_json, description
FROM feature_pricing_configs
""")
rows = session.execute(sql).mappings().all()
configs: dict[str, FeatureConfig] = {}
for row in rows:
key = str(row["feature_key"] or "").strip()
if not key:
continue
configs[key] = FeatureConfig(
feature_key=key,
name=str(row["name"] or key),
emoji=str(row["emoji"] or ""),
is_enabled=bool(row["is_enabled"]),
fixed_cost=_to_float(row["fixed_cost"]),
profit_multiplier=_to_float(row["profit_multiplier"], 1.0),
dynamic_unit_cost=_to_float(row["dynamic_unit_cost"]),
billing_mode=str(row["billing_mode"] or "model_based"),
price_cap=_to_float(row["price_cap"]),
model_pricing=_parse_model_pricing(row["model_pricing_json"]),
description=str(row["description"] or ""),
)
return configs
finally:
if session is not None:
try:
session.close()
except Exception: # noqa: BLE001
pass
def _get_cache() -> dict[str, FeatureConfig]:
"""TTL 内返回缓存,否则重新 load;DB 异常/表不存在时返回内置兜底配置。"""
global _cache
now = time.monotonic()
with _lock:
if _cache is not None and now - _cache[0] < CACHE_TTL_SECONDS:
return _cache[1]
try:
loaded = _load_all()
except Exception: # noqa: BLE001 - 表不存在/DB 不可用时静默回落
logger.info("feature_pricing_configs 读取失败,使用内置兜底配置", exc_info=True)
return _fallback_configs()
# DB 可用但表为空:同样回落兜底(保证爆款现状不被改变)
if not loaded:
fallback = _fallback_configs()
with _lock:
_cache = (now, fallback)
return fallback
# 以兜底为底(DB 未配置的 feature_key 仍有兜底),DB 行覆盖
merged = _fallback_configs()
merged.update(loaded)
with _lock:
_cache = (now, merged)
return merged
def get_feature_config(feature_key: str) -> Optional[FeatureConfig]:
"""获取指定功能配置,未知 key 返回 None。"""
key = str(feature_key or "").strip()
if not key:
return None
return _get_cache().get(key)
def _global_points_enabled() -> bool:
"""全局积分总开关(兼容 api / worker 运行时),取不到时默认关闭。"""
try:
from packages.shared import get_shared_settings
return bool(get_shared_settings().points_enabled)
except Exception: # noqa: BLE001
pass
try:
from app.config import settings
return bool(getattr(settings, "points_enabled", False))
except Exception: # noqa: BLE001
return False
def is_feature_enabled(feature_key: str) -> bool:
"""功能是否启用并扣费:全局 points_enabled AND 功能 is_enabled。"""
cfg = get_feature_config(feature_key)
if cfg is None:
return False
return bool(cfg.is_enabled) and _global_points_enabled()
def calculate_price(feature_key: str, dynamic_cost: float = 0.0) -> tuple[float, dict]:
"""按公式计算最终积分并返回明细。
price = (dynamic_cost + fixed_cost) × profit_multiplier
price_cap > 0 时封顶(取 min)。
功能未启用 → (0.0, breakdown{is_enabled: False, charged: False})。
"""
cfg = get_feature_config(feature_key)
dynamic = max(0.0, _to_float(dynamic_cost))
if cfg is None or not cfg.is_enabled:
return 0.0, {
"feature_key": feature_key,
"is_enabled": False,
"charged": False,
"dynamic_cost": dynamic,
"fixed_cost": 0.0,
"profit_multiplier": 1.0,
"price_cap": 0.0,
"final_price": 0.0,
}
fixed = max(0.0, cfg.fixed_cost)
multiplier = cfg.profit_multiplier if cfg.profit_multiplier > 0 else 1.0
raw_price = (dynamic + fixed) * multiplier
cap = cfg.price_cap if cfg.price_cap and cfg.price_cap > 0 else 0.0
final_price = min(raw_price, cap) if cap else raw_price
final_price = round(float(final_price), 2)
breakdown = {
"feature_key": cfg.feature_key,
"is_enabled": True,
"charged": True,
"dynamic_cost": round(dynamic, 4),
"fixed_cost": float(fixed),
"profit_multiplier": float(multiplier),
"price_cap": float(cap),
"raw_price": round(float(raw_price), 4),
"final_price": final_price,
}
return final_price, breakdown
def lookup_model_price(
model_pricing: dict,
model_key: str,
resolution: str,
has_video_input: bool,
) -> Optional[float]:
"""从 model_pricing dict 取模型单价,兼容两种常见 JSON 结构。
1. 嵌套:{model: {resolution: {"true"/"false": price}}}
(内层 bool key 也兼容直接 bool / 省略)
2. 扁平:{"model|resolution|true_or_false": price}
(分隔符支持 | / : / , / 空格;bool 段可省略)
取不到返回 None。
"""
if not isinstance(model_pricing, dict):
return None
model = str(model_key or "").strip()
res = str(resolution or "").strip()
flag = "true" if has_video_input else "false"
# 1. 嵌套
model_node = model_pricing.get(model)
if isinstance(model_node, dict):
res_node = model_node.get(res)
if isinstance(res_node, dict):
# 精确 bool key 命中才返回;不做“只有一个值就取”的模糊匹配
# (否则缺失 true 时会错误地取到 false 价,破坏旧版回落规则)
if flag in res_node:
return _to_float(res_node[flag]) if res_node[flag] is not None else None
if has_video_input in res_node:
val = res_node[has_video_input]
return _to_float(val) if val is not None else None
elif isinstance(res_node, (int, float)):
return float(res_node)
# 2. 扁平
for sep in ("|", ":", ",", " "):
for key in (
f"{model}{sep}{res}{sep}{flag}",
f"{model}{sep}{res}",
):
if key in model_pricing:
value = model_pricing[key]
return _to_float(value) if value is not None else None
return None
def refresh_feature_configs() -> None:
"""清空缓存(下次读取重新 load DB;测试/admin 改配置后可手动调)。"""
global _cache
with _lock:
_cache = None
+77 -14
View File
@@ -2,17 +2,21 @@
v1.6.1: 按产品决策,智能混剪/AI数字人/AI配音/抖音解析/改写/标题/封面 全部免费,
仅保留声音克隆合成(voice_clone_synth)的扣点逻辑;声音克隆训练保持免费。
爆款视频(viral_video)走动态定价,见本文件 VIRAL_VIDEO_MODEL_PRICES + calculate_viral_video_credits。
爆款视频(viral_video)走动态定价,计费参数 DB 化(feature_pricing_configs,
见 feature_pricing_service),calculate_viral_video_credits 从配置读取单价/
固定成本/利润系数/封顶,DB 不可用时回落兜底配置。
"""
from __future__ import annotations
import math
# ============ 爆款视频动态定价 (#2151) ============
# key = (model_id, resolution, has_video_input),单位:
# - billing_mode=token: 元/百万tokens(输出)
# - billing_mode=per_second: 元/秒(视频时长)
from packages.domain import feature_pricing_service
# ============ 爆款视频动态定价 ============
# 单价/固定成本/利润系数已 DB 化(feature_pricing_configs,feature_key=viral_video),
# 由 feature_pricing_service 读取(300s 缓存),DB 不可用时回落内置兜底配置。
# 以下三个常量仅为向后兼容保留(旧引用方/兜底场景),值取自兜底配置。
VIRAL_VIDEO_MODEL_PRICES: dict[tuple[str, str, bool], float] = {
("seedance-2.5", "480p", False): 70.0,
("seedance-2.5", "720p", False): 70.0,
@@ -33,9 +37,9 @@ VIRAL_VIDEO_MODEL_PRICES: dict[tuple[str, str, bool], float] = {
("wan-3.0", "1080p", False): 1.2,
}
# 固定成本(元):VLM 分析 + LLM 文案 + TTS + OSS + 服务器
# 固定成本(元):VLM 分析 + LLM 文案 + TTS + OSS + 服务器(兜底默认值)
VIRAL_VIDEO_FIXED_COST = 0.15
# 利润系数
# 利润系数(兜底默认值)
VIRAL_VIDEO_PROFIT_MULTIPLIER = 1.3
# Seedance 输出帧率
VIRAL_VIDEO_FPS = 24
@@ -222,17 +226,22 @@ def calculate_viral_video_credits_with_breakdown(
) -> tuple[float, dict]:
"""计算爆款视频所需积分(1 积分 = 1 元),并返回计费公式明细。
单价/固定成本/利润系数/封顶从 feature_pricing_configs(viral_video)读取;
DB 不可用时回落与现状一致的内置兜底配置。
公式:
tokens = duration * width * height * fps / 1024
video_cost = tokens / 1_000_000 * model_token_price
total = round((video_cost + fixed_cost) * profit_multiplier, 2)
price_cap > 0 时封顶取 min
若传入 actual_tokens 则用它替代计算值。
Returns:
(credits, breakdown) 二元组:
- credits: 四舍五入保留两位小数的最终积分
- breakdown: dict,包含 tokens / video_cost / fixed_cost / profit_multiplier /
model_price / width / height / fps 字段,便于前端展示计费明细。
model_price / width / height / fps / feature_enabled / charged / price_cap
字段,便于前端展示计费明细。功能关闭时 credits=0、charged=False。
"""
w = max(1, int(width or 1))
h = max(1, int(height or 1))
@@ -242,11 +251,36 @@ def calculate_viral_video_credits_with_breakdown(
cfg = get_viral_video_model_config(prefix)
res_key = _infer_resolution_key(w, h)
billing = cfg.get("billing_mode", "token")
key = (prefix, res_key, bool(has_video_input))
price = VIRAL_VIDEO_MODEL_PRICES.get(key)
dur = max(1, int(duration_seconds or 15))
# ── 从 DB 配置(兜底内置)取计费参数 ──
feature_cfg = feature_pricing_service.get_feature_config("viral_video")
# 注意:此处 feature_enabled 只表示“功能自身开关”,不并入全局 points_enabled
# 总开关(保持与旧版计费函数行为一致:价格照常计算)。全局总开关由业务层
# (route/worker)通过 feature_pricing_service.is_feature_enabled 统一把关。
feature_enabled = bool(feature_cfg.is_enabled) if feature_cfg is not None else True
model_pricing = feature_cfg.model_pricing if feature_cfg is not None else {}
fixed_cost = float(feature_cfg.fixed_cost) if feature_cfg is not None else float(VIRAL_VIDEO_FIXED_COST)
multiplier = (
float(feature_cfg.profit_multiplier)
if feature_cfg is not None and feature_cfg.profit_multiplier > 0
else float(VIRAL_VIDEO_PROFIT_MULTIPLIER)
)
price_cap = float(feature_cfg.price_cap) if feature_cfg is not None else 0.0
# 单价:优先配置 dict;复刻旧版回落规则——精确 key 取不到时,回落
# seedance-2.5 同分辨率 False 单价;最终兜底 70.0。
price = feature_pricing_service.lookup_model_price(model_pricing, prefix, res_key, bool(has_video_input))
if price is None:
# 配置表未命中:先尝试配置里的 seedance-2.5/False
if prefix != "seedance-2.5" or bool(has_video_input):
price = feature_pricing_service.lookup_model_price(model_pricing, "seedance-2.5", res_key, False)
if price is None:
key = (prefix, res_key, bool(has_video_input))
price = VIRAL_VIDEO_MODEL_PRICES.get(key)
if price is None:
price = VIRAL_VIDEO_MODEL_PRICES.get(("seedance-2.5", res_key, False), 70.0)
dur = max(1, int(duration_seconds or 15))
if billing == "per_second":
tokens = 0.0
video_cost = dur * float(price)
@@ -259,13 +293,40 @@ def calculate_viral_video_credits_with_breakdown(
video_cost = tokens / 1_000_000.0 * float(price)
billing_unit = "token"
total = (video_cost + VIRAL_VIDEO_FIXED_COST) * VIRAL_VIDEO_PROFIT_MULTIPLIER
if not feature_enabled:
# 功能关闭(is_enabled=false 或全局 points 关闭):不扣费,明细照旧返回
credits = 0.0
raw_total = (video_cost + fixed_cost) * multiplier
breakdown = {
"tokens": float(tokens),
"video_cost": float(video_cost),
"fixed_cost": float(fixed_cost),
"profit_multiplier": float(multiplier),
"price_cap": float(price_cap or 0.0),
"model_price": float(price),
"model_key": prefix,
"billing_mode": billing,
"billing_unit": billing_unit,
"width": int(w),
"height": int(h),
"fps": int(effective_fps),
"duration": dur,
"feature_enabled": False,
"charged": False,
"raw_price": round(float(raw_total), 4),
}
return credits, breakdown
total = (video_cost + fixed_cost) * multiplier
if price_cap and price_cap > 0:
total = min(total, price_cap)
credits = round(float(total), 2)
breakdown = {
"tokens": float(tokens),
"video_cost": float(video_cost),
"fixed_cost": float(VIRAL_VIDEO_FIXED_COST),
"profit_multiplier": float(VIRAL_VIDEO_PROFIT_MULTIPLIER),
"fixed_cost": float(fixed_cost),
"profit_multiplier": float(multiplier),
"price_cap": float(price_cap or 0.0),
"model_price": float(price),
"model_key": prefix,
"billing_mode": billing,
@@ -274,6 +335,8 @@ def calculate_viral_video_credits_with_breakdown(
"height": int(h),
"fps": int(effective_fps),
"duration": dur,
"feature_enabled": True,
"charged": True,
}
return credits, breakdown
+45 -4
View File
@@ -87,6 +87,9 @@ class ViralVideoJob:
user_id: str
images: list[str] = field(default_factory=list)
pre_trusted_images: list[str] | None = (
None # #2172 信任链预热结果(Seedream AI 化后的 URL 列表),与 images 顺序对应
)
industry: str = ""
target_customer: str = ""
persona_id: str = ""
@@ -188,13 +191,45 @@ class ViralVideoJob:
self.updated_at = datetime.now(timezone.utc)
def resume_from_image_analyzed(self, **kwargs) -> None:
if self.status not in (ViralVideoStatus.IMAGE_ANALYZED, ViralVideoStatus.PENDING):
"""阶段2入口:允许从 IMAGE_ANALYZED/PENDING 首次进入,也允许从 COPY_GENERATED/COMPLETED/FAILED 重新生成文案。
重新生成时清空上一轮文案产物(copy_result/intent_result/storyboard/generated_copy_text),
并重置 completed_at/result_video_url/error_msg,确保前端轮询能看到新的阶段2进度。
"""
_allowed = (
ViralVideoStatus.IMAGE_ANALYZED,
ViralVideoStatus.PENDING,
ViralVideoStatus.COPY_GENERATED,
ViralVideoStatus.COMPLETED,
ViralVideoStatus.FAILED,
)
if self.status not in _allowed:
raise ValueError(f"Cannot resume from {self.status} to copy-gen")
_is_regen = self.status in (
ViralVideoStatus.COPY_GENERATED,
ViralVideoStatus.COMPLETED,
ViralVideoStatus.FAILED,
)
for k, v in kwargs.items():
if hasattr(self, k) and v not in (None, "", []):
setattr(self, k, v)
if _is_regen:
# 清空上一轮文案/视频产物,避免前端拿到旧数据
self.intent_result = None
self.copy_result = None
self.storyboard = None
self.generated_copy_text = ""
self.result_video_url = ""
self.current_stage = ""
self.phase_message = ""
self.error_msg = ""
self.completed_at = None
self.heartbeat_at = None
_now = datetime.now(timezone.utc)
self.started_at = _now
self.heartbeat_at = _now
self.status = ViralVideoStatus.RUNNING
self.updated_at = datetime.now(timezone.utc)
self.updated_at = _now
def resume_from_copy_generated(self, edited_copy: str | None = None) -> None:
"""阶段2->阶段3:用户确认/编辑口播文案,开始跑 TTS+单次Seedance渲染。"""
@@ -203,14 +238,20 @@ class ViralVideoJob:
if edited_copy and isinstance(self.copy_result, dict):
self.copy_result = {**self.copy_result, "voiceover_script": edited_copy}
self.generated_copy_text = edited_copy
_now = datetime.now(timezone.utc)
self.started_at = _now
self.heartbeat_at = _now
self.status = ViralVideoStatus.RUNNING
self.updated_at = datetime.now(timezone.utc)
self.updated_at = _now
def resume_from_confirm(self) -> None:
if self.status != ViralVideoStatus.WAIT_USER_CONFIRM:
raise ValueError(f"Cannot resume from {self.status}")
_now = datetime.now(timezone.utc)
self.started_at = _now
self.heartbeat_at = _now
self.status = ViralVideoStatus.RUNNING
self.updated_at = datetime.now(timezone.utc)
self.updated_at = _now
def mark_completed(self, video_url: str) -> None:
self.status = ViralVideoStatus.COMPLETED
File diff suppressed because it is too large Load Diff
+62
View File
@@ -0,0 +1,62 @@
"""AI 配置版本号管理 — Redis 通知机制.
admin 后台修改 ai_models / ai_capability_configs 后调用 bump_version(),
SaaS 端 AIRouter 每次取配置前比对版本号,变了才重新查 DB。
Redis key: xiaoxia:ai_config:version = 时间戳字符串
"""
from __future__ import annotations
import logging
import time
from typing import Optional
logger = logging.getLogger(__name__)
_REDIS_KEY = "xiaoxia:ai_config:version"
def _get_redis_client():
"""获取 Redis 客户端(复用 Celery broker 连接)."""
try:
import redis as _redis
from packages.shared.config import get_shared_settings
settings = get_shared_settings()
redis_url = getattr(settings, "redis_url", None) or getattr(
settings, "celery_broker_url", "redis://localhost:6379/0"
)
return _redis.Redis.from_url(redis_url, decode_responses=True, socket_timeout=2)
except Exception as e:
logger.warning("AI config version: Redis 客户端初始化失败: %s", e)
return None
def bump_version() -> str:
"""写入新版本号(当前时间戳),返回版本号字符串。失败返回空串。"""
r = _get_redis_client()
if r is None:
logger.warning("AI config bump_version: Redis 不可用,跳过版本号更新")
return ""
try:
ver = str(int(time.time() * 1000))
r.set(_REDIS_KEY, ver)
logger.info("AI config version bumped to %s", ver)
return ver
except Exception as e:
logger.warning("AI config bump_version 失败: %s", e)
return ""
def get_version() -> Optional[str]:
"""读取当前版本号。Redis 不可用或异常返回 None。"""
r = _get_redis_client()
if r is None:
return None
try:
return r.get(_REDIS_KEY)
except Exception as e:
logger.warning("AI config get_version 失败: %s", e)
return None
+516
View File
@@ -0,0 +1,516 @@
"""AI 模型路由层 — 统一模型配置读取与客户端构建.
业务代码通过 AIRouter 获取客户端,不再硬编码 model/api_key/base_url。
配置来源:DB ai_capability_configs JOIN ai_models → Redis 版本号缓存 → SharedSettings fallback。
使用方式:
from packages.shared.ai_router import ai_router
client = ai_router.get_llm_client("intent_parsing")
result = client.chat_completion(messages=[...])
"""
from __future__ import annotations
import logging
import threading
from dataclasses import dataclass
from packages.shared.config import get_shared_settings
logger = logging.getLogger(__name__)
# ── 配置数据类 ──────────────────────────────────────────────────────────────
@dataclass(frozen=True)
class ModelConfig:
"""单个 AI 模型配置(来自 ai_models 表)"""
id: str
name: str
provider: str
model_key: str
api_key: str
api_base: str
api_version: str | None
status: str
@dataclass(frozen=True)
class CapabilityConfig:
"""业务能力配置(来自 ai_capability_configs JOIN ai_models)"""
capability_key: str
capability_name: str
primary_model: ModelConfig | None
lite_model: ModelConfig | None
fallback_model: ModelConfig | None
timeout_seconds: int
max_retries: int
max_tokens: int | None
temperature: float | None
concurrency: int
extra_params: dict
is_enabled: bool
# ── 简单包装类(TTS / ImageGen / VideoGen)──────────────────────────────────
class TTSClient:
"""TTS 客户端(简单配置持有者,实际调用由 CosyVoiceService 完成)"""
def __init__(
self,
provider: str,
api_key: str,
base_url: str,
model: str,
timeout: int = 60,
extra_params: dict | None = None,
):
self.provider = provider
self.api_key = api_key
self.base_url = base_url
self.model = model
self.timeout = timeout
self.extra_params = extra_params or {}
@property
def is_available(self) -> bool:
return bool(self.api_key and self.base_url and self.model)
class ImageGenClient:
"""图片生成客户端(简单配置持有者)"""
def __init__(
self,
provider: str,
api_key: str,
base_url: str,
model: str,
timeout: int = 60,
extra_params: dict | None = None,
):
self.provider = provider
self.api_key = api_key
self.base_url = base_url
self.model = model
self.timeout = timeout
self.extra_params = extra_params or {}
@property
def is_available(self) -> bool:
return bool(self.api_key and self.base_url and self.model)
class VideoGenClient:
"""视频生成客户端(简单配置持有者)"""
def __init__(
self,
provider: str,
api_key: str,
base_url: str,
model: str,
timeout: int = 600,
extra_params: dict | None = None,
):
self.provider = provider
self.api_key = api_key
self.base_url = base_url
self.model = model
self.timeout = timeout
self.extra_params = extra_params or {}
@property
def is_available(self) -> bool:
return bool(self.api_key and self.base_url and self.model)
# ── DB Session 获取 ─────────────────────────────────────────────────────────
def _get_session():
"""获取 DB session,兼容 api / worker / 独立脚本场景"""
from packages.adapters.sqlalchemy_impl.session import SessionLocal
if SessionLocal is not None:
return SessionLocal()
try:
from worker_app.db import SessionLocal as WorkerSL
if WorkerSL is not None:
return WorkerSL()
except ImportError:
pass
try:
from app.db import SessionLocal as ApiSL
if ApiSL is not None:
return ApiSL()
except ImportError:
pass
return None
# ── 核心路由类 ──────────────────────────────────────────────────────────────
class AIRouter:
"""AI 模型路由器 — 统一配置读取与客户端构建.
缓存策略:
1. 本地内存缓存 {capability_key: CapabilityConfig}
2. 每次读取前比对 Redis 版本号,变了则清缓存重新查 DB
3. DB 无配置 / Redis 不可用 → fallback 到 SharedSettings 环境变量
"""
def __init__(self):
self._cache: dict[str, CapabilityConfig] = {}
self._local_ver: str | None = None
self._lock = threading.Lock()
def _check_version(self) -> bool:
"""检查 Redis 版本号,变了返回 True(需要刷新缓存)"""
from packages.shared.ai_config_version import get_version
current_ver = get_version()
if current_ver is None:
return False
if self._local_ver != current_ver:
return True
return False
def _load_from_db(self, capability_key: str) -> CapabilityConfig | None:
"""从 DB 加载配置(ai_capability_configs JOIN ai_models)"""
session = _get_session()
if session is None:
logger.warning("AI Router: 无法获取 DB session")
return None
try:
from sqlalchemy import text
sql = text("""
SELECT
cc.capability_key, cc.capability_name, cc.timeout_seconds,
cc.max_retries, cc.max_tokens, cc.temperature,
cc.concurrency, cc.extra_params, cc.is_enabled,
pm.id AS pm_id, pm.name AS pm_name, pm.provider AS pm_provider,
pm.model_key AS pm_model_key, pm.api_key AS pm_api_key,
pm.api_base AS pm_api_base, pm.api_version AS pm_api_version,
pm.status AS pm_status,
lm.id AS lm_id, lm.name AS lm_name, lm.provider AS lm_provider,
lm.model_key AS lm_model_key, lm.api_key AS lm_api_key,
lm.api_base AS lm_api_base, lm.api_version AS lm_api_version,
lm.status AS lm_status,
fm.id AS fm_id, fm.name AS fm_name, fm.provider AS fm_provider,
fm.model_key AS fm_model_key, fm.api_key AS fm_api_key,
fm.api_base AS fm_api_base, fm.api_version AS fm_api_version,
fm.status AS fm_status
FROM ai_capability_configs cc
LEFT JOIN ai_models pm ON cc.primary_model_id = pm.id AND pm.deleted_at IS NULL
LEFT JOIN ai_models lm ON cc.lite_model_id = lm.id AND lm.deleted_at IS NULL
LEFT JOIN ai_models fm ON cc.fallback_model_id = fm.id AND fm.deleted_at IS NULL
WHERE cc.capability_key = :key AND cc.is_enabled = true
""")
row = session.execute(sql, {"key": capability_key}).first()
if not row:
return None
def _to_model(prefix: str) -> ModelConfig | None:
mid = getattr(row, f"{prefix}_id", None)
if not mid:
return None
return ModelConfig(
id=mid,
name=getattr(row, f"{prefix}_name", "") or "",
provider=getattr(row, f"{prefix}_provider", "") or "",
model_key=getattr(row, f"{prefix}_model_key", "") or "",
api_key=getattr(row, f"{prefix}_api_key", "") or "",
api_base=getattr(row, f"{prefix}_api_base", "") or "",
api_version=getattr(row, f"{prefix}_api_version", None),
status=getattr(row, f"{prefix}_status", "active") or "active",
)
return CapabilityConfig(
capability_key=row.capability_key,
capability_name=row.capability_name,
primary_model=_to_model("pm"),
lite_model=_to_model("lm"),
fallback_model=_to_model("fm"),
timeout_seconds=row.timeout_seconds or 30,
max_retries=row.max_retries or 1,
max_tokens=row.max_tokens,
temperature=row.temperature,
concurrency=row.concurrency or 2,
extra_params=row.extra_params or {},
is_enabled=row.is_enabled,
)
except Exception as e:
logger.warning("AI Router: DB 查询失败 (key=%s): %s", capability_key, e)
return None
finally:
session.close()
def get_capability(self, key: str) -> CapabilityConfig | None:
"""获取业务能力配置(带缓存)"""
with self._lock:
if self._check_version():
self._cache.clear()
from packages.shared.ai_config_version import get_version
self._local_ver = get_version()
if key in self._cache:
return self._cache[key]
config = self._load_from_db(key)
if config:
self._cache[key] = config
return config
def _get_model_or_fallback(self, cap: CapabilityConfig, variant: str = "primary") -> ModelConfig | None:
"""按 variant 选择模型,不存在则降级。
- primary: primary → fallback
- lite: lite → primary
- fallback: fallback → primary(修复点:此前 fallback variant 被忽略,错误地使用了 primary 模型)
"""
if variant == "fallback":
if cap.fallback_model:
return cap.fallback_model
if cap.primary_model:
return cap.primary_model
elif variant == "lite":
if cap.lite_model:
return cap.lite_model
if cap.primary_model:
return cap.primary_model
else: # primary
if cap.primary_model:
return cap.primary_model
if cap.fallback_model:
return cap.fallback_model
return None
# ── 构建客户端 ─────────────────────────────────────────────────────────
def _build_llm_client(self, model: ModelConfig, cap: CapabilityConfig):
"""构建 LLM 客户端 — 返回 DoubaoClient 实例"""
from packages.shared.ai_client import DoubaoClient
return DoubaoClient(
api_key=model.api_key,
base_url=model.api_base,
model=model.model_key,
timeout=cap.timeout_seconds,
max_retries=cap.max_retries,
max_tokens=cap.max_tokens,
temperature=cap.temperature,
extra_params=cap.extra_params,
provider=model.provider,
)
def _build_vision_client(self, model: ModelConfig, cap: CapabilityConfig):
"""构建 VLM 客户端 — 返回 DoubaoClient 实例(DoubaoClient 已支持 vision_completion)"""
from packages.shared.ai_client import DoubaoClient
return DoubaoClient(
api_key=model.api_key,
base_url=model.api_base,
model=model.model_key,
timeout=cap.timeout_seconds,
max_retries=cap.max_retries,
max_tokens=cap.max_tokens,
temperature=cap.temperature,
extra_params=cap.extra_params,
provider=model.provider,
)
def _build_tts_client(self, model: ModelConfig, cap: CapabilityConfig) -> TTSClient:
return TTSClient(
provider=model.provider,
api_key=model.api_key,
base_url=model.api_base,
model=model.model_key,
timeout=cap.timeout_seconds,
extra_params=cap.extra_params,
)
def _build_image_gen_client(self, model: ModelConfig, cap: CapabilityConfig) -> ImageGenClient:
return ImageGenClient(
provider=model.provider,
api_key=model.api_key,
base_url=model.api_base,
model=model.model_key,
timeout=cap.timeout_seconds,
extra_params=cap.extra_params,
)
def _build_video_gen_client(self, model: ModelConfig, cap: CapabilityConfig) -> VideoGenClient:
return VideoGenClient(
provider=model.provider,
api_key=model.api_key,
base_url=model.api_base,
model=model.model_key,
timeout=cap.timeout_seconds,
extra_params=cap.extra_params,
)
# ── 公开接口 ────────────────────────────────────────────────────────────
def get_llm_client(self, key: str, variant: str = "primary"):
"""获取 LLM 客户端(返回 DoubaoClient 实例)"""
cap = self.get_capability(key)
if cap and cap.is_enabled:
model = self._get_model_or_fallback(cap, variant)
if model and model.api_key:
return self._build_llm_client(model, cap)
return self._fallback_llm_client(key)
def get_vision_client(self, key: str, variant: str = "primary"):
"""获取 VLM 客户端(返回 DoubaoClient 实例)"""
cap = self.get_capability(key)
if cap and cap.is_enabled:
model = self._get_model_or_fallback(cap, variant)
if model and model.api_key:
return self._build_vision_client(model, cap)
return self._fallback_vision_client(key)
def get_tts_client(self, key: str = "tts") -> TTSClient | None:
"""获取 TTS 客户端"""
cap = self.get_capability(key)
if cap and cap.is_enabled and cap.primary_model and cap.primary_model.api_key:
return self._build_tts_client(cap.primary_model, cap)
return self._fallback_tts_client()
def get_image_gen_client(self, key: str = "image_generation") -> ImageGenClient | None:
"""获取图片生成客户端"""
cap = self.get_capability(key)
if cap and cap.is_enabled and cap.primary_model and cap.primary_model.api_key:
return self._build_image_gen_client(cap.primary_model, cap)
return self._fallback_image_gen_client()
def get_video_gen_client(self, key: str = "video_generation") -> VideoGenClient | None:
"""获取视频生成客户端"""
cap = self.get_capability(key)
if cap and cap.is_enabled and cap.primary_model and cap.primary_model.api_key:
return self._build_video_gen_client(cap.primary_model, cap)
return self._fallback_video_gen_client()
# ── Fallback 方法(读 SharedSettings 环境变量)──────────────────────────
def _fallback_llm_client(self, key: str):
"""Fallback LLM 客户端 — 从 settings 读取配置,不硬编码"""
settings = get_shared_settings()
model_map = {
"intent_parsing": (settings.doubao_fast_model, settings.doubao_base_url, settings.doubao_api_key),
"copy_fusion": (settings.doubao_fast_model, settings.doubao_base_url, settings.doubao_api_key),
"storyboard": (settings.doubao_model, settings.doubao_base_url, settings.doubao_api_key),
"copy_review": (settings.doubao_model, settings.doubao_base_url, settings.doubao_api_key),
"asset_classify": (settings.doubao_model, settings.doubao_base_url, settings.doubao_api_key),
}
if key in model_map:
model_id, base_url, api_key = model_map[key]
else:
model_id = settings.doubao_model
base_url = settings.doubao_base_url
api_key = settings.doubao_api_key
if not api_key:
return None
from packages.shared.ai_client import DoubaoClient
return DoubaoClient(
provider="volcengine",
api_key=api_key,
base_url=base_url,
model=model_id,
timeout=settings.doubao_timeout,
max_retries=settings.doubao_max_retries,
)
def _fallback_vision_client(self, key: str):
"""Fallback VLM 客户端 — 从 settings 读取 dashscope 配置,不硬编码"""
settings = get_shared_settings()
api_key = getattr(settings, "dashscope_api_key", "")
if not api_key:
return None
base_url = getattr(settings, "dashscope_base_url", "") or ""
model = getattr(settings, "dashscope_model", "") or getattr(settings, "doubao_vision_model", "")
from packages.shared.ai_client import DoubaoClient
return DoubaoClient(
provider="dashscope",
api_key=api_key,
base_url=base_url,
model=model,
timeout=15,
)
def _fallback_tts_client(self) -> TTSClient | None:
settings = get_shared_settings()
api_key = getattr(settings, "cosyvoice_api_key", "")
if not api_key:
return None
base_url = getattr(settings, "cosyvoice_base_url", "")
model = getattr(settings, "cosyvoice_model", "")
return TTSClient(provider="dashscope", api_key=api_key, base_url=base_url, model=model)
def _fallback_image_gen_client(self) -> ImageGenClient | None:
settings = get_shared_settings()
api_key = getattr(settings, "doubao_api_key", "")
if not api_key:
return None
base_url = getattr(settings, "doubao_base_url", "")
model = getattr(settings, "doubao_image_model", "")
return ImageGenClient(
provider="volcengine",
api_key=api_key,
base_url=base_url,
model=model,
timeout=getattr(settings, "doubao_image_timeout", 60),
)
def _fallback_video_gen_client(self) -> VideoGenClient | None:
settings = get_shared_settings()
api_key = getattr(settings, "doubao_api_key", "")
if not api_key:
return None
base_url = getattr(settings, "doubao_base_url", "")
model = getattr(settings, "doubao_video_model", "")
return VideoGenClient(
provider="volcengine",
api_key=api_key,
base_url=base_url,
model=model,
timeout=getattr(settings, "doubao_video_timeout", 600),
)
def invalidate(self):
"""清空本地缓存"""
with self._lock:
self._cache.clear()
self._local_ver = None
# ── 全局单例 ──────────────────────────────────────────────────────────────
ai_router = AIRouter()
+51 -10
View File
@@ -502,6 +502,7 @@ def call_llm(
max_tokens: int = 2048,
model: str | None = None,
system_prompt: str | None = None,
timeout: int | None = None,
) -> object:
"""调用豆包大模型(文本对话),返回解析后的 JSON(dict/list)或原文字符串;失败返回 None。
@@ -521,7 +522,7 @@ def call_llm(
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt},
]
raw = client.chat_completion(messages, temperature=temperature, max_tokens=max_tokens, model=model)
raw = client.chat_completion(messages, temperature=temperature, max_tokens=max_tokens, model=model, timeout=timeout)
if raw is None:
return None
try:
@@ -604,6 +605,24 @@ def call_vision(
return raw
def preheat_trust_chain(portrait_descriptions: list[str], *, timeout: int = 120) -> list[str] | None:
"""#2174 信任链预热(t2i版):用 VLM 分析出的人物外貌描述,跑 Seedream 文生图,
生成的信任产物 URL 可传给 call_video_generation(pre_trusted_images=...)。
- portrait_descriptions: VLM输出的portrait_prompt列表(中文人物外貌描述)
- 成功返回与输入同序的信任图URL列表;任意一张失败返回None(调用方回退到纯t2v)
- 必须传VLM人物描述,不传reference_images,走纯t2i路径才是方舟信任产物
"""
client = get_doubao_client()
if not client.is_available:
return None
try:
return client.preheat_trust_chain(portrait_descriptions, timeout=timeout)
except Exception as e:
logger.error("[ai_service] preheat_trust_chain 异常: %s", e, exc_info=True)
return None
def call_video_generation(
prompt: str,
*,
@@ -617,21 +636,25 @@ def call_video_generation(
reference_images: list[str] | None = None,
reference_audios: list[str] | None = None,
reference_videos: list[str] | None = None,
pre_trusted_images: list[str] | None = None,
) -> dict | None:
"""调用 Seedance 2.5 生成视频(v1.6.1 单次出片版)。
"""调用 Seedance / Wan 视频生成(v1.6.2 多模型版 + #2172 信任链预热)。
成功返回 {"video_path": str, "usage": dict | None}(usage 含 completion_tokens),失败返回 None。
v1.6.1 关键约束(避免 20min 卡死):
- 参考音频/视频/多图全部放进 content 数组并带 role=reference_audio/reference_video/reference_image;
- 纯首帧无参考时(first_frame 模式),Seedance 2.5 强制 ratio=adaptive;
传了参考音/视/多图时走 omni_reference 模式,ratio 可指定为 9:16(客户端内部自动判断)。
- ratio 默认 9:16(竖屏),客户端会根据是否有参考自动在 first_frame/adaptive 与 omni/9:16 间切换;
若创建任务因 ratio 报错(HTTP 400),客户端会自动回退到 adaptive 再试一次。
失败时错误详情会写入 client.last_video_error,可通过 get_last_video_error() 读取:
{"error_code": str, "user_message": str, "status_code": int, "detail": str, ...}
"""
client = get_doubao_client()
if not client.is_available:
logger.warning("[ai_service] 豆包客户端未配置,跳过视频生成")
msg = "豆包客户端未配置(DOUBAO_API_KEY 缺失),跳过视频生成"
logger.warning("[ai_service] %s", msg)
# 写入 last_video_error 供上层读取
client.last_video_error = {
"error_code": "auth_error",
"user_message": "视频生成服务未配置,请联系管理员。",
"status_code": 0,
"detail": msg,
}
return None
effective_ratio = ratio or "9:16"
try:
@@ -647,10 +670,28 @@ def call_video_generation(
reference_images=reference_images,
reference_audios=reference_audios,
reference_videos=reference_videos,
pre_trusted_images=pre_trusted_images,
)
if effective_ratio:
kwargs["ratio"] = effective_ratio
return client.video_generation(**kwargs)
except Exception as e:
logger.error("[ai_service] call_video_generation 异常: %s", e, exc_info=True)
client.last_video_error = {
"error_code": "unknown",
"user_message": f"视频生成异常:{e!s}"[:200],
"status_code": 0,
"detail": str(e),
}
return None
def get_last_video_error() -> dict:
"""读取最近一次视频生成失败的详细错误(含 error_code/user_message/status_code/detail)。
成功或未调用过返回空 dict。
"""
try:
client = get_doubao_client()
return client.get_last_video_error() if hasattr(client, "get_last_video_error") else {}
except Exception:
return {}
+2
View File
@@ -51,6 +51,8 @@ task_routes = {
"ai_avatar_render.execute": {"queue": QUEUE_GENERATION},
# GPU MuseTalk 口型同步(用户等成片,链路子任务全部走 generation 避免跨队列阻塞)
"lipsync_gpu_process_async": {"queue": QUEUE_GENERATION},
# #2076 Ditto 蚂蚁数字人口型同步(走 generation 队列,避免跨队列阻塞)
"lipsync_ditto_process_async": {"queue": QUEUE_GENERATION},
"lipsync_tts.synthesize_and_submit": {"queue": QUEUE_GENERATION},
"lipsync_tts.poll_mediakit_status": {"queue": QUEUE_GENERATION},
"lipsync_tts.persist_output_video": {"queue": QUEUE_GENERATION},
+142 -19
View File
@@ -21,11 +21,59 @@ import httpx
from packages.shared.config import get_shared_settings
# 网络/超时类异常父类集合:覆盖 Timeout/Connect/Network/ReadTimeout/WriteTimeout/PoolTimeout
_HTTP_NETWORK_ERRORS = ()
try:
_HTTP_NETWORK_ERRORS = (httpx.TimeoutException, httpx.NetworkError)
except Exception:
_HTTP_NETWORK_ERRORS = (Exception,)
_HTTP_STATUS_ERROR = httpx.HTTPStatusError if hasattr(httpx, "HTTPStatusError") else Exception
logger = logging.getLogger(__name__)
_DASHSCOPE_CLIENT_SINGLETON: "DashScopeClient | None" = None
def _classify_dashscope_error(status_code: int, body: str, task_msg: str = "") -> tuple[str, str]:
"""DashScope 错误分类,返回 (error_code, user_message)。"""
body_lower = (body or "").lower()
msg_in_body = task_msg or ""
try:
import json as _json
parsed = _json.loads(body or "{}")
if isinstance(parsed, dict):
msg_in_body = msg_in_body or str(parsed.get("message", "") or "")
except Exception:
pass
if status_code in (401, 403):
return "auth_error", "Wan 3.0 服务鉴权失败(DASHSCOPE_API_KEY 无效或过期),请联系管理员。"
if status_code == 429 or "rate" in body_lower or "throttl" in body_lower:
return "rate_limit", "Wan 3.0 服务繁忙(限流),请稍等1-2分钟后重试。"
if status_code == 400 and any(
kw in body_lower for kw in ("portrait", "真人", "人脸", "肖像", "content_violation", "risk", "blocked")
):
return (
"portrait_intercept",
"参考素材包含真人照片或违规内容被安全策略拦截,请移除真人图片或调整文案后重试。",
)
if status_code == 404 or ("not found" in body_lower) or ("model" in body_lower and "not exist" in body_lower):
return "model_not_found", "Wan 3.0 模型未开通或模型ID无效,请联系管理员。"
if status_code in (402, 400) and ("quota" in body_lower or "billing" in body_lower or "insufficient" in body_lower):
return "quota_exceeded", "Wan 3.0 服务配额不足,请联系管理员充值或稍后重试。"
if status_code == 400:
return "invalid_param", f"Wan 3.0 参数错误:{msg_in_body or body[:200]}"
if status_code == 0:
return "network_error", "Wan 3.0 服务连接失败(网络超时),请稍后重试。"
# 任务内失败
if task_msg and any(kw in task_msg.lower() for kw in ("portrait", "真人", "人脸", "violation", "blocked")):
return "portrait_intercept", "Wan 3.0 视频内容被安全策略拦截,请调整文案或参考图后重试。"
detail = msg_in_body or body[:200]
return "unknown", f"Wan 3.0 视频生成失败(HTTP {status_code}):{detail}"
class DashScopeClient:
"""阿里云 DashScope 异步 API 客户端(Wan 3.0 等视频生成)。"""
@@ -38,11 +86,24 @@ class DashScopeClient:
self.poll_interval: int = int(getattr(settings, "dashscope_video_poll_interval", 10) or 10)
self.total_timeout: int = int(getattr(settings, "dashscope_video_timeout", 900) or 900)
self.max_retries: int = 2
self.last_video_error: dict = {}
@property
def is_available(self) -> bool:
return bool(self.api_key)
def get_last_video_error(self) -> dict:
return dict(self.last_video_error or {})
def _set_error(self, error_code: str, user_message: str, status_code: int = 0, detail: str = "", **extra) -> None:
self.last_video_error = {
"error_code": error_code,
"user_message": user_message,
"status_code": status_code,
"detail": detail[:500] if detail else "",
**extra,
}
def video_generation(
self,
prompt: str,
@@ -57,12 +118,15 @@ class DashScopeClient:
) -> dict | None:
"""调用 DashScope 异步视频合成接口,轮询完成后下载到本地。
返回 {"video_path": str, "usage": dict | None};失败返回 None。
返回 {"video_path": str, "usage": dict | None};失败返回 None,错误详情写入 self.last_video_error。
"""
self.last_video_error = {}
if not self.is_available:
self._set_error("auth_error", "Wan 3.0 API key 未配置,请联系管理员。", detail="dashscope api_key empty")
logger.error("[dashscope] API key 未配置,无法调用视频生成")
return None
if not prompt or not prompt.strip():
self._set_error("invalid_param", "视频生成提示词不能为空。", detail="empty prompt")
return None
# DashScope 分辨率参数:720P / 1080P / 480P(大写 P)
@@ -106,18 +170,27 @@ class DashScopeClient:
ds_res,
bool(image_url),
)
logger.info("[dashscope] 创建任务 payload: model=%s params=%s", model, params)
# 创建任务
task_id: str | None = None
last_err: Exception | None = None
last_sc = 0
last_body = ""
for attempt in range(self.max_retries + 1):
try:
resp = httpx.post(create_url, headers=headers, json=payload, timeout=60)
sc = int(getattr(resp, "status_code", 0) or 0)
body_text = (getattr(resp, "text", "") or "")[:1500]
body_text = (getattr(resp, "text", "") or "")[:2000]
last_sc = sc
last_body = body_text
if sc >= 400:
logger.error("[dashscope] 创建任务 HTTP %d: %s", sc, body_text)
resp.raise_for_status()
if sc >= 500 and attempt < self.max_retries:
time.sleep(0.5 * (2**attempt))
continue
err_code, user_msg = _classify_dashscope_error(sc, body_text)
self._set_error(err_code, user_msg, sc, body_text, model=model)
return None
data = resp.json()
tid = (data.get("output") or {}).get("task_id")
if tid:
@@ -126,17 +199,34 @@ class DashScopeClient:
# 部分情况下 code != 错误
code = data.get("code")
if code and code != "":
last_err = RuntimeError(f"dashscope create failed: {body_text[:300]}")
err_code, user_msg = _classify_dashscope_error(400, body_text, str(code))
self._set_error(err_code, user_msg, sc, body_text, model=model)
return None
else:
last_err = RuntimeError(f"create ok but no task_id: {str(data)[:300]}")
except Exception as e:
last_err = e
self._set_error("unknown", "Wan 3.0 响应格式异常,未返回任务ID", sc, str(data)[:500], model=model)
return None
except _HTTP_NETWORK_ERRORS as ne:
last_sc = 0
last_body = f"network error: {ne}"
logger.warning(
"[dashscope] 网络异常 %s,重试 %d/%d", type(ne).__name__, attempt + 1, self.max_retries + 1
)
if attempt < self.max_retries:
time.sleep(0.5 * (2**attempt))
continue
logger.error("[dashscope] 创建任务最终失败: %s", last_err)
self._set_error("network_error", "Wan 3.0 服务连接失败(网络超时),请稍后重试。", 0, str(ne))
return None
except Exception as _e:
if attempt < self.max_retries:
time.sleep(0.5 * (2**attempt))
continue
logger.error("[dashscope] 创建任务最终失败: %s", _e)
self._set_error("unknown", f"Wan 3.0 创建任务异常:{_e!s}"[:200], 0, str(_e))
return None
if not task_id:
if not self.last_video_error:
err_code, user_msg = _classify_dashscope_error(last_sc, last_body)
self._set_error(err_code, user_msg, last_sc, last_body, model=model)
return None
# 轮询任务
@@ -144,16 +234,26 @@ class DashScopeClient:
deadline = time.time() + self.total_timeout
video_url: str | None = None
usage: dict | None = None
poll_count = 0
last_status = ""
while time.time() < deadline:
poll_count += 1
try:
r = httpx.get(poll_url, headers=headers, timeout=30)
if int(getattr(r, "status_code", 0) or 0) >= 400:
logger.warning("[dashscope] 轮询 HTTP %d", r.status_code)
time.sleep(self.poll_interval)
continue
psc = int(getattr(r, "status_code", 0) or 0)
pbody = (getattr(r, "text", "") or "")[:1500]
if psc >= 400:
logger.warning("[dashscope] 轮询 HTTP %d: %s", psc, pbody[:300])
if poll_count < 3:
time.sleep(self.poll_interval)
continue
err_code, user_msg = _classify_dashscope_error(psc, pbody)
self._set_error(err_code, user_msg, psc, pbody, task_id=task_id)
return None
d = r.json()
out = d.get("output") or {}
task_status = out.get("task_status") or d.get("task_status") or ""
last_status = task_status
if task_status == "SUCCEEDED":
video_url = out.get("video_url") or ""
usage = d.get("usage")
@@ -165,22 +265,41 @@ class DashScopeClient:
if video_url:
logger.info("[dashscope] 任务 %s 完成: %s", task_id, video_url[:120])
break
logger.error("[dashscope] 任务 %s SUCCEEDED 但无 video_url", task_id)
logger.error("[dashscope] 任务 %s SUCCEEDED 但无 video_url: %s", task_id, str(d)[:500])
self._set_error(
"unknown",
"Wan 3.0 任务成功但未返回视频URL,请联系管理员。",
200,
str(d)[:500],
task_id=task_id,
)
return None
if task_status in ("FAILED", "FAILED_WITH_ERROR", "ERROR"):
msg = out.get("message") or d.get("message") or "unknown error"
msg = out.get("message") or d.get("message") or out.get("error_msg") or "unknown error"
logger.error("[dashscope] 任务 %s 失败: %s", task_id, msg)
err_code, user_msg = _classify_dashscope_error(200, "", msg)
self._set_error(err_code, user_msg, 200, msg, task_id=task_id, last_status=task_status)
return None
if task_status in ("CANCELED", "CANCELLED"):
logger.warning("[dashscope] 任务 %s 被取消", task_id)
self._set_error("unknown", "Wan 3.0 任务被取消。", 200, "task cancelled", task_id=task_id)
return None
# PENDING / RUNNING / SUSPENDED → 继续轮询
logger.debug("[dashscope] 任务 %s 状态 %s,继续轮询", task_id, task_status)
if poll_count % 5 == 0:
logger.info("[dashscope] 轮询中 task=%s status=%s polls=%d", task_id, task_status, poll_count)
except Exception as e:
logger.warning("[dashscope] 轮询异常: %s", e)
time.sleep(self.poll_interval)
if not video_url:
logger.error("[dashscope] 任务 %s 轮询超时(%ds)", task_id, self.total_timeout)
self._set_error(
"network_error",
f"Wan 3.0 视频生成超时(>{self.total_timeout}s),任务仍在排队,请稍后重试。",
0,
f"timeout after {self.total_timeout}s, polls={poll_count}, last_status={last_status}",
task_id=task_id,
last_status=last_status,
)
return None
# 下载视频
@@ -193,19 +312,23 @@ class DashScopeClient:
out_path = os.path.join(out_dir, f"wan_{safe_tid}{suffix}")
try:
with httpx.stream("GET", video_url, timeout=300, follow_redirects=True) as resp:
if int(getattr(resp, "status_code", 0) or 0) >= 400:
logger.error("[dashscope] 下载 HTTP %d", resp.status_code)
dsc = int(getattr(resp, "status_code", 0) or 0)
if dsc >= 400:
logger.error("[dashscope] 下载 HTTP %d", dsc)
self._set_error("network_error", "Wan 3.0 视频下载失败(HTTP错误),请稍后重试。", dsc)
return None
with open(out_path, "wb") as f:
for chunk in resp.iter_bytes(chunk_size=1024 * 256):
if chunk:
f.write(chunk)
except Exception as e:
logger.error("[dashscope] 下载视频失败: %s", e)
logger.error("[dashscope] 下载视频失败: %s", e, exc_info=True)
self._set_error("network_error", f"Wan 3.0 视频下载失败:{e!s}"[:200], 0, str(e))
return None
size = os.path.getsize(out_path) if os.path.exists(out_path) else 0
if size < 1024:
logger.error("[dashscope] 下载文件过小: %d bytes", size)
self._set_error("unknown", "Wan 3.0 视频下载文件过小,请稍后重试。", 0, f"downloaded only {size} bytes")
return None
logger.info("[dashscope] 视频已下载: %s (%d bytes)", out_path, size)
return {"video_path": out_path, "usage": usage}
+1 -1
View File
@@ -334,7 +334,7 @@ class SharedStorageService(StoragePort):
storage_key = self.normalize_storage_key(storage_key_or_url)
try:
signed = sign_bucket.sign_url("GET", storage_key, expires_seconds)
signed = sign_bucket.sign_url("GET", storage_key, expires_seconds, slash_safe=True)
logger.info(
"signed URL generated for key=%s prefix=%s",
storage_key[:80],
+1 -1
View File
@@ -57,7 +57,7 @@ if [ "$TARGET_ENV" = "staging" ]; then
fi
# 共用 secrets 直接导出(如果存在)
SHARED_SECRETS="OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET COSYVOICE_API_KEY DASHSCOPE_API_KEY MEDIAKIT_API_KEY DOUBAO_API_KEY DOUBAO_MODEL DOUBAO_FAST_MODEL DOUBAO_BASE_URL DOUBAO_VISION_MODEL DOUBAO_VISION_LITE_MODEL DOUBAO_VISION_USE_LITE WECHAT_APP_ID WECHAT_APP_SECRET TIKHUB_API_KEY APIZERO_API_KEY GPU_WORKER_TOKEN"
SHARED_SECRETS="OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET COSYVOICE_API_KEY DASHSCOPE_API_KEY MEDIAKIT_API_KEY DOUBAO_API_KEY DOUBAO_MODEL DOUBAO_FAST_MODEL DOUBAO_BASE_URL DOUBAO_VISION_MODEL DOUBAO_VISION_LITE_MODEL DOUBAO_VISION_USE_LITE DOUBAO_IMAGE_MODEL DOUBAO_IMAGE_SIZE DOUBAO_IMAGE_TIMEOUT DOUBAO_FAST_MODEL DOUBAO_TIMEOUT DOUBAO_MAX_RETRIES WECHAT_APP_ID WECHAT_APP_SECRET TIKHUB_API_KEY APIZERO_API_KEY GPU_WORKER_TOKEN"
for var in $SHARED_SECRETS; do
value="${!var:-}"
# 已经在环境中了,无需额外操作
+80
View File
@@ -0,0 +1,80 @@
"""爆款视频 5 套 Prompt 模板种子脚本(#2040)。
幂等:以 (prompt_type, version) 为唯一键,存在则更新(UPSERT),重复执行结果一致。
用法:
python scripts/seed_viral_video_prompts.py # 自动用应用配置连库
DATABASE_URL=postgresql+psycopg2://... python scripts/seed_viral_video_prompts.py
"""
from __future__ import annotations
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import sqlalchemy as sa # noqa: E402
from packages.application.viral_video.prompts import DEFAULT_TEMPLATES # noqa: E402
def _engine():
database_url = os.environ.get("DATABASE_URL")
if database_url:
return sa.create_engine(database_url)
# 复用应用自身配置
from packages.config import get_shared_settings
url = str(get_shared_settings().database_url)
return sa.create_engine(url.replace("postgresql+asyncpg://", "postgresql+psycopg2://"))
UPSERT_SQL = sa.text("""
INSERT INTO viral_video_prompt_templates
(name, prompt_type, version, system_prompt, user_prompt_template,
example_output, is_active, updated_at)
VALUES
(:name, :prompt_type, :version, :system_prompt, :user_prompt_template,
:example_output, TRUE, :now_ts)
ON CONFLICT (prompt_type, version) DO UPDATE SET
name = EXCLUDED.name,
system_prompt = EXCLUDED.system_prompt,
user_prompt_template = EXCLUDED.user_prompt_template,
example_output = EXCLUDED.example_output,
is_active = TRUE,
updated_at = :now_ts
""")
def seed(engine) -> int:
count = 0
from datetime import datetime, timezone
now_ts = datetime.now(timezone.utc)
with engine.begin() as conn:
for item in DEFAULT_TEMPLATES:
conn.execute(
UPSERT_SQL,
{
"name": item["name"],
"prompt_type": item["prompt_type"],
"version": item["version"],
"system_prompt": item["system_prompt"],
"user_prompt_template": item["user_prompt_template"],
"example_output": item["example_output"],
"now_ts": now_ts,
},
)
count += 1
return count
def main() -> int:
engine = _engine()
count = seed(engine)
print(f"seed 完成:{count} 套模板已写入/更新(image_analysis/intent_parsing/copy_fusion/storyboard/review)")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+61 -24
View File
@@ -1,4 +1,5 @@
"""Additional unit tests to hit uncovered lines for diff-coverage >=60%."""
from __future__ import annotations
import json
@@ -13,15 +14,20 @@ from packages.shared.ai_client import DoubaoClient
class _FakeSettings:
doubao_api_key = "test-key"
doubao_model = "test-model"
doubao_fast_model = "test-fast-model"
doubao_model = "doubao-seed-2-1-pro-260915"
doubao_fast_model = "doubao-seed-2-1-lite-260915"
doubao_base_url = "https://ark.cn-beijing.volces.com/api/v3"
doubao_timeout = 10
doubao_max_retries = 0
doubao_vision_model = "test-vision"
doubao_vision_lite_model = "test-vision-lite"
doubao_vision_model = "doubao-seed-2-1-pro-260915"
doubao_vision_lite_model = "doubao-seed-2-1-lite-260915"
doubao_vision_use_lite = False
doubao_embedding_model = "test-embedding"
doubao_embedding_model = "doubao-embedding-vision-251215"
doubao_video_model = "doubao-seedance-2-5-260628"
doubao_video_timeout = 480
doubao_video_poll_interval = 10
doubao_image_model = "doubao-seedream-5-0-pro-260628"
doubao_image_timeout = 120
def _make_client(api_key: str = "test-key") -> DoubaoClient:
@@ -129,26 +135,50 @@ from packages.domain.atom_clip_tagger import parse_vision_response
class TestParseVisionResponseEdgeCases:
def test_person_count_type_error_defaults_zero(self):
text = json.dumps({
"scene": [], "objects": [], "action": [], "shot": "", "has_text": False,
"person_count": "not-an-int", "text_content": "", "caption": "x",
})
text = json.dumps(
{
"scene": [],
"objects": [],
"action": [],
"shot": "",
"has_text": False,
"person_count": "not-an-int",
"text_content": "",
"caption": "x",
}
)
r = parse_vision_response(text)
assert r["person_count"] == 0
def test_person_count_out_of_range_clamped(self):
text = json.dumps({
"scene": [], "objects": [], "action": [], "shot": "", "has_text": False,
"person_count": 10, "text_content": "", "caption": "x",
})
text = json.dumps(
{
"scene": [],
"objects": [],
"action": [],
"shot": "",
"has_text": False,
"person_count": 10,
"text_content": "",
"caption": "x",
}
)
r = parse_vision_response(text)
assert r["person_count"] == 3
def test_person_count_negative_clamped(self):
text = json.dumps({
"scene": [], "objects": [], "action": [], "shot": "", "has_text": False,
"person_count": -5, "text_content": "", "caption": "x",
})
text = json.dumps(
{
"scene": [],
"objects": [],
"action": [],
"shot": "",
"has_text": False,
"person_count": -5,
"text_content": "",
"caption": "x",
}
)
r = parse_vision_response(text)
assert r["person_count"] == 0
@@ -159,10 +189,18 @@ class TestParseVisionResponseEdgeCases:
def test_caption_truncation_at_80(self):
long_caption = "描" * 100
text = json.dumps({
"scene": [], "objects": [], "action": [], "shot": "", "has_text": False,
"person_count": 0, "text_content": "", "caption": long_caption,
})
text = json.dumps(
{
"scene": [],
"objects": [],
"action": [],
"shot": "",
"has_text": False,
"person_count": 0,
"text_content": "",
"caption": long_caption,
}
)
r = parse_vision_response(text)
assert len(r["caption"]) == 80
@@ -196,9 +234,7 @@ class TestNarrativeMatchNonDictClipTags:
def test_non_dict_clip_tags_are_skipped(self):
a1 = _FA("a1", tags=[])
clip_map = {"a1": [None, "bad", {"scene": ["工厂"], "objects": [], "action": []}, 123]}
matched, unmatched = match_assets_by_script_tags(
[a1], script_tags=["工厂"], clip_ai_tags_by_asset=clip_map
)
matched, unmatched = match_assets_by_script_tags([a1], script_tags=["工厂"], clip_ai_tags_by_asset=clip_map)
assert [a.id for a in matched] == ["a1"]
@@ -231,6 +267,7 @@ class _FQuery:
class TestUpdateCaptionEmbedding:
def _make_repo(self, session):
from packages.adapters.sqlalchemy_impl.asset_atom_clip_repository import SQLAlchemyAssetAtomClipRepository
repo = SQLAlchemyAssetAtomClipRepository.__new__(SQLAlchemyAssetAtomClipRepository)
repo.session = session
return repo
+3 -3
View File
@@ -17,7 +17,7 @@ def mock_settings():
doubao_api_key="test-api-key",
doubao_model="doubao-pro-32k",
doubao_base_url="https://ark.example.com/api/v3",
doubao_timeout=30,
doubao_timeout=45,
doubao_max_retries=2,
)
yield mock
@@ -37,7 +37,7 @@ def client_without_key():
doubao_api_key="",
doubao_model="doubao-pro-32k",
doubao_base_url="https://ark.example.com/api/v3",
doubao_timeout=30,
doubao_timeout=45,
doubao_max_retries=2,
)
yield DoubaoClient()
@@ -52,7 +52,7 @@ class TestDoubaoClientInit:
assert client.api_key == "test-api-key"
assert client.model == "doubao-pro-32k"
assert client.base_url == "https://ark.example.com/api/v3"
assert client.timeout == 30
assert client.timeout == 45
assert client.max_retries == 2
def test_base_url_strips_trailing_slash(self, mock_settings):
+635
View File
@@ -0,0 +1,635 @@
"""#2170 Seedream 图片生成 + 方舟信任链单测。"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import httpx
from packages.shared.ai_client import DoubaoClient
def _make_client(**overrides):
client = DoubaoClient.__new__(DoubaoClient)
client.api_key = overrides.get("api_key", "test-key")
client.base_url = overrides.get("base_url", "https://ark.cn-beijing.volces.com/api/v3")
client.model = "doubao-model"
client.vision_model = "doubao-vision"
client.embedding_model = "doubao-embedding"
client.image_model = overrides.get("image_model", "doubao-seedream-5-0-pro-260628")
client.image_timeout = overrides.get("image_timeout", 120)
client.timeout = overrides.get("timeout", 30)
client.max_retries = overrides.get("max_retries", 0)
client.last_video_error = {}
client.last_image_error = {}
return client
def _fake_time(base=1000.0, stable_calls=50, big=9e9):
"""返回 time.time 替身:前 stable_calls 次返回 base+i,之后返回 big+i。
Python 3.12 logging.LogRecord.__init__ 内部会调 time.time(),
用有限 iter 会 StopIteration,因此必须用无限生成器。
"""
state = {"n": 0}
def _t():
n = state["n"]
state["n"] += 1
if n < stable_calls:
return base + n
return big + n
return _t
# ── Seedream 图片生成单测 ──────────────────────────────────────────
class TestImageGenerationHappyPath:
def test_returns_none_when_no_api_key(self):
client = _make_client(api_key="")
assert client.image_generation("p") is None
err = client.get_last_image_error()
assert err["error_code"] == "auth_error"
def test_returns_none_on_empty_prompt(self):
client = _make_client()
assert client.image_generation(" ") is None
err = client.get_last_image_error()
assert err["error_code"] == "invalid_param"
def test_text_to_image_success(self):
client = _make_client()
captured = {}
ok_resp = MagicMock()
ok_resp.status_code = 200
ok_resp.json.return_value = {"data": [{"url": "https://cdn.example.com/i.png"}], "usage": {"tokens": 1}}
ok_resp.raise_for_status = MagicMock()
ok_resp.text = ""
def fake_post(url, **kwargs):
captured["url"] = url
captured["json"] = kwargs.get("json")
return ok_resp
with patch("packages.shared.ai_client.httpx.post", side_effect=fake_post):
result = client.image_generation("一只可爱的猫", size="1K")
assert result is not None
assert result["url"] == "https://cdn.example.com/i.png"
assert "/images/generations" in captured["url"]
assert captured["json"]["model"] == "doubao-seedream-5-0-pro-260628"
assert captured["json"]["size"] == "1K"
assert "image" not in captured["json"]
def test_image_to_image_single_ref_passed_as_string(self):
client = _make_client()
captured = {}
ok_resp = MagicMock(status_code=200)
ok_resp.json.return_value = {"data": [{"url": "https://cdn.example.com/out.png"}]}
ok_resp.raise_for_status = MagicMock()
ok_resp.text = ""
def fake_post(url, **kwargs):
captured["json"] = kwargs.get("json")
return ok_resp
with patch("packages.shared.ai_client.httpx.post", side_effect=fake_post):
client.image_generation("保持五官", reference_images=["https://img/x.jpg"])
assert captured["json"]["image"] == "https://img/x.jpg"
def test_image_to_image_multiple_refs_passed_as_list(self):
client = _make_client()
captured = {}
ok_resp = MagicMock(status_code=200)
ok_resp.json.return_value = {"data": [{"url": "https://cdn.example.com/out.png"}]}
ok_resp.raise_for_status = MagicMock()
def fake_post(url, **kwargs):
captured["json"] = kwargs.get("json")
return ok_resp
refs = [f"https://img/{i}.jpg" for i in range(3)]
with patch("packages.shared.ai_client.httpx.post", side_effect=fake_post):
client.image_generation("保持", reference_images=refs)
assert captured["json"]["image"] == refs
def test_400_sensitive_returns_portrait_intercept(self):
client = _make_client(max_retries=0)
bad_resp = MagicMock(status_code=400)
bad_resp.text = '{"error":{"code":"ContentRisk","message":"sensitive content detected"}}'
bad_resp.json.return_value = {"error": {"code": "ContentRisk"}}
bad_resp.raise_for_status.side_effect = httpx.HTTPStatusError("bad", request=MagicMock(), response=bad_resp)
with patch("packages.shared.ai_client.httpx.post", return_value=bad_resp):
assert client.image_generation("p", reference_images=["https://img/x.jpg"]) is None
err = client.get_last_image_error()
assert err["error_code"] == "portrait_intercept"
def test_500_retries_then_fails(self):
client = _make_client(max_retries=1)
bad_resp = MagicMock(status_code=500)
bad_resp.text = "internal error"
bad_resp.json.return_value = {"error": {"message": "internal"}}
bad_resp.raise_for_status.side_effect = httpx.HTTPStatusError("500", request=MagicMock(), response=bad_resp)
with (
patch("packages.shared.ai_client.httpx.post", return_value=bad_resp) as mp,
patch("packages.shared.ai_client.time.sleep", return_value=None),
):
assert client.image_generation("p") is None
assert mp.call_count == 2
err = client.get_last_image_error()
assert err["error_code"] == "network_error"
# ── 信任链集成单测 ────────────────────────────────────────────────
class TestTrustChainIntegration:
def test_pre_trusted_images_replace_original_refs(self, tmp_path):
"""#2174: 传 pre_trusted_images(预热好的t2i信任图)时,替换原image_url/ref_imgs发给Seedance,不再现场跑Seedream。"""
client = _make_client()
captured_calls = []
task_ok = MagicMock(status_code=200)
task_ok.json.return_value = {"id": "t-trust"}
task_ok.raise_for_status = MagicMock()
task_ok.text = ""
poll_ok = MagicMock(status_code=200)
poll_ok.json.return_value = {"status": "succeeded", "content": {"video_url": "https://cdn.example.com/v.mp4"}}
poll_ok.raise_for_status = MagicMock()
class FakeStream:
def __init__(self):
self._c = [b"OK"]
self._it = iter(self._c)
def __enter__(self):
return self
def __exit__(self, *a):
return False
def raise_for_status(self):
return None
def iter_bytes(self, chunk_size=None):
return self._it
def fake_post(url, **kwargs):
captured_calls.append({"url": url, "json": kwargs.get("json")})
return task_ok
fake_uuid = MagicMock()
fake_uuid.hex = "00000001"
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.httpx.get", return_value=poll_ok),
patch("packages.shared.ai_client.httpx.stream", return_value=FakeStream()),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time(stable_calls=2)),
patch("packages.shared.ai_client.uuid.uuid4", return_value=fake_uuid),
patch("packages.shared.ai_client.get_shared_settings") as ms,
):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=60,
doubao_video_model="doubao-seedance-2-5-260628",
)
out = client.video_generation(
"人物在海边散步",
image_url="https://img/raw.jpg",
pre_trusted_images=["https://ai.example.com/trusted.png"],
duration=5,
ratio="9:16",
resolution="720p",
output_dir=str(tmp_path),
)
assert out is not None
# 只有一次 Seedance 调用(不现场跑Seedream)
assert len(captured_calls) == 1
assert "/contents/generations/tasks" in captured_calls[0]["url"]
seedance_payload = captured_calls[0]["json"]
content = seedance_payload["content"]
img_items = [c for c in content if c.get("type") == "image_url"]
assert len(img_items) == 1
assert img_items[0]["image_url"]["url"] == "https://ai.example.com/trusted.png"
assert img_items[0]["role"] == "reference_image"
assert seedance_payload["ratio"] == "9:16"
def test_no_reference_image_skips_seedream(self, tmp_path):
client = _make_client()
captured_calls = []
task_ok = MagicMock(status_code=200)
task_ok.json.return_value = {"id": "t-t2v"}
task_ok.raise_for_status = MagicMock()
poll_ok = MagicMock(status_code=200)
poll_ok.json.return_value = {"status": "succeeded", "content": {"video_url": "https://cdn.example.com/v.mp4"}}
poll_ok.raise_for_status = MagicMock()
class FakeStream:
def __init__(self):
self._it = iter([b"OK"])
def __enter__(self):
return self
def __exit__(self, *a):
return False
def raise_for_status(self):
return None
def iter_bytes(self, chunk_size=None):
return self._it
def fake_post(url, **kwargs):
captured_calls.append({"url": url, "json": kwargs.get("json")})
return task_ok
fake_uuid = MagicMock()
fake_uuid.hex = "00000002"
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.httpx.get", return_value=poll_ok),
patch("packages.shared.ai_client.httpx.stream", return_value=FakeStream()),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time(stable_calls=2)),
patch("packages.shared.ai_client.uuid.uuid4", return_value=fake_uuid),
patch("packages.shared.ai_client.get_shared_settings") as ms,
):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=60,
doubao_video_model="doubao-seedance-2-5-260628",
)
out = client.video_generation("海边日落", duration=5, ratio="9:16", output_dir=str(tmp_path))
assert out is not None
assert len(captured_calls) == 1
assert "/contents/generations/tasks" in captured_calls[0]["url"]
content = captured_calls[0]["json"]["content"]
assert all(c.get("type") != "image_url" for c in content)
def test_no_preheated_images_falls_back_to_first_frame_mode(self, tmp_path):
"""#2174: 无 pre_trusted_images 时原图走 first_frame 模式(ratio=adaptive),不再现场跑 Seedream。"""
client = _make_client(max_retries=0)
captured_calls = []
task_ok = MagicMock(status_code=200)
task_ok.json.return_value = {"id": "t-fb"}
task_ok.raise_for_status = MagicMock()
poll_ok = MagicMock(status_code=200)
poll_ok.json.return_value = {"status": "succeeded", "content": {"video_url": "https://cdn.example.com/v.mp4"}}
poll_ok.raise_for_status = MagicMock()
class FakeStream:
def __init__(self):
self._it = iter([b"OK"])
def __enter__(self):
return self
def __exit__(self, *a):
return False
def raise_for_status(self):
return None
def iter_bytes(self, chunk_size=None):
return self._it
def fake_post(url, **kwargs):
captured_calls.append({"url": url, "json": kwargs.get("json")})
return task_ok
fake_uuid = MagicMock()
fake_uuid.hex = "00000003"
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.httpx.get", return_value=poll_ok),
patch("packages.shared.ai_client.httpx.stream", return_value=FakeStream()),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time(stable_calls=2)),
patch("packages.shared.ai_client.uuid.uuid4", return_value=fake_uuid),
patch("packages.shared.ai_client.get_shared_settings") as ms,
):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=60,
doubao_video_model="doubao-seedance-2-5-260628",
)
out = client.video_generation(
"海边散步",
image_url="https://img/raw.jpg",
duration=5,
ratio="9:16",
output_dir=str(tmp_path),
)
assert out is not None
# 不现场跑 Seedream,只有一次 Seedance 调用
assert len(captured_calls) == 1
seedance_payload = captured_calls[0]["json"]
content = seedance_payload["content"]
img_items = [c for c in content if c.get("type") == "image_url"]
assert len(img_items) == 1
assert img_items[0]["image_url"]["url"] == "https://img/raw.jpg"
assert img_items[0]["role"] == "first_frame"
assert seedance_payload["ratio"] == "adaptive"
# ── image_generation 补充分支覆盖 ─────────────────────────────────
class TestImageGenerationBranches:
"""覆盖 image_generation 的错误分类/重试/结构异常等分支。"""
def test_401_returns_auth_error(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=401, text='{"error":{}}')
r.json.return_value = {"error": {}}
r.raise_for_status.side_effect = httpx.HTTPStatusError("a", request=MagicMock(), response=r)
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "auth_error"
def test_404_returns_model_not_found(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=404, text="not found")
r.json.return_value = {"error": {"message": "model not found"}}
r.raise_for_status.side_effect = httpx.HTTPStatusError("a", request=MagicMock(), response=r)
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "model_not_found"
def test_400_quota_returns_quota_exceeded(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=400, text="insufficient balance quota exceeded")
r.json.return_value = {"error": {"message": "quota"}}
r.raise_for_status.side_effect = httpx.HTTPStatusError("a", request=MagicMock(), response=r)
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "quota_exceeded"
def test_400_rate_limit_returns_rate_limit(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=400, text="too many requests, rate limit exceeded")
r.json.return_value = {"error": {"message": "rate"}}
r.raise_for_status.side_effect = httpx.HTTPStatusError("a", request=MagicMock(), response=r)
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "rate_limit"
def test_400_generic_returns_invalid_param(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=400, text="bad parameter size")
r.json.return_value = {"error": {"message": "bad"}}
r.raise_for_status.side_effect = httpx.HTTPStatusError("a", request=MagicMock(), response=r)
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "invalid_param"
def test_200_but_no_url_returns_none(self):
client = _make_client(max_retries=0)
r = MagicMock(status_code=200, text="")
r.json.return_value = {"data": [{"no_url": True}]} # 缺 url 字段
r.raise_for_status = MagicMock()
with patch("packages.shared.ai_client.httpx.post", return_value=r):
assert client.image_generation("p") is None
assert client.get_last_image_error()["error_code"] == "unknown"
def test_network_error_retries_then_fails(self):
client = _make_client(max_retries=1)
import httpcore
with (
patch("packages.shared.ai_client.httpx.post", side_effect=httpx.ConnectError("no network")),
patch("packages.shared.ai_client.time.sleep", return_value=None),
):
assert client.image_generation("p") is None
err = client.get_last_image_error()
assert err["error_code"] == "network_error"
def test_get_last_image_error_returns_copy(self):
client = _make_client()
client.last_image_error = {"error_code": "x"}
e1 = client.get_last_image_error()
e1["error_code"] = "mutated"
assert client.last_image_error["error_code"] == "x"
# ── 信任链分支覆盖 ────────────────────────────────────────
class TestTrustChainBranches:
def test_dashscope_provider_skips_trust_chain(self, tmp_path):
"""provider=dashscope 时不走信任链(Wan 模型由 dashscope_client 处理,在我们分支之前已经 return)。
这里测 doubao 分支:信任链默认触发,验证 DashScope 分发路径不受影响。"""
# 该测试实际覆盖 video_generation 入口的 dashscope 分发:缺 DASHSCOPE_API_KEY 时返回 auth_error
client = _make_client()
with (patch("packages.shared.ai_client.get_shared_settings") as ms,):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=1,
doubao_video_model="doubao-seedance-2-5-260628",
)
# DashScope 不可用时返回 auth_error(不是信任链相关错误)
result = client.video_generation(
"p",
output_dir=str(tmp_path),
model="wan-3.0",
image_url="https://img/x.jpg",
)
assert result is None
err = client.get_last_video_error()
# 不论是否走信任链,DashScope 无 key 时返回 auth_error
assert err["error_code"] == "auth_error"
def test_trust_chain_partial_seedream_success_falls_back(self, tmp_path):
"""#2174: 预热结果为空/None 时回退原图直传(走#2166的400→t2v自动降级路径)。"""
client = _make_client(max_retries=0)
# 预热结果传 None → 应该直接用原图发给 Seedance
def fake_post(url, **kwargs):
# Seedance create task(收到原图直传时会调用)
t = MagicMock(status_code=200, text="")
t.json.return_value = {"id": "t-partial"}
t.raise_for_status = MagicMock()
return t
poll_ok = MagicMock(status_code=200, text="")
poll_ok.json.return_value = {"status": "succeeded", "content": {"video_url": "https://cdn.example.com/v.mp4"}}
poll_ok.raise_for_status = MagicMock()
class FS:
def __init__(self):
self._it = iter([b"OK"])
def __enter__(self):
return self
def __exit__(self, *a):
return False
def raise_for_status(self):
return None
def iter_bytes(self, chunk_size=None):
return self._it
fake_uuid = MagicMock()
fake_uuid.hex = "00000004"
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.httpx.get", return_value=poll_ok),
patch("packages.shared.ai_client.httpx.stream", return_value=FS()),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time(stable_calls=50)),
patch("packages.shared.ai_client.uuid.uuid4", return_value=fake_uuid),
patch("packages.shared.ai_client.get_shared_settings") as ms,
):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=60,
doubao_video_model="doubao-seedance-2-5-260628",
)
out = client.video_generation(
"p",
image_url="https://img/a.jpg",
reference_images=["https://img/b.jpg"],
duration=5,
ratio="9:16",
output_dir=str(tmp_path),
)
assert out is not None
# 最终发给 Seedance 的图应是原始 https://img/a.jpg(回退),role=first_frame(因为 has_extra_refs=False 只有 1 张)
# 注意:回退后 ref_imgs 是原始 ["https://img/b.jpg"],所以 has_extra_refs=True,role=reference_image
# 断言最终 Seedance payload 里的 image_url 是原图(不是 AI 图)
def test_default_values_on_missing_settings(self):
"""getattr 兜底:settings 缺 image_timeout 字段时使用默认 120。"""
client = _make_client()
# 直接调用 image_generation,让它走一次完整流程(成功路径),验证 timeout 取值
ok = MagicMock(status_code=200, text="")
ok.json.return_value = {"data": [{"url": "https://ai.example.com/x.png"}]}
ok.raise_for_status = MagicMock()
captured_kwargs = {}
def fake_post(url, **kw):
captured_kwargs["timeout"] = kw.get("timeout")
return ok
with patch("packages.shared.ai_client.httpx.post", side_effect=fake_post):
r = client.image_generation("p", timeout=None) # 不传 timeout,走 self.image_timeout=120
assert r is not None
assert captured_kwargs["timeout"] == 120
def test_trust_chain_uses_preheated_t2i_images(self, tmp_path):
"""#2174: 传 pre_trusted_images(预热好的t2i信任图)时,替换原参考图发给Seedance。"""
client = _make_client()
captured = []
task_ok = MagicMock(status_code=200, text="")
task_ok.json.return_value = {"id": "t-refonly"}
task_ok.raise_for_status = MagicMock()
poll_ok = MagicMock(status_code=200, text="")
poll_ok.json.return_value = {"status": "succeeded", "content": {"video_url": "https://cdn.example.com/v.mp4"}}
poll_ok.raise_for_status = MagicMock()
class FS:
def __init__(self):
self._it = iter([b"OK"])
def __enter__(self):
return self
def __exit__(self, *a):
return False
def raise_for_status(self):
return None
def iter_bytes(self, chunk_size=None):
return self._it
def fake_post(url, **kw):
captured.append({"url": url, "json": kw.get("json")})
return task_ok
fu = MagicMock()
fu.hex = "0000000a"
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.httpx.get", return_value=poll_ok),
patch("packages.shared.ai_client.httpx.stream", return_value=FS()),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time(stable_calls=3)),
patch("packages.shared.ai_client.uuid.uuid4", return_value=fu),
patch("packages.shared.ai_client.get_shared_settings") as ms,
):
ms.return_value = MagicMock(
doubao_video_poll_interval=0,
doubao_video_timeout=60,
doubao_video_model="doubao-seedance-2-5-260628",
)
out = client.video_generation(
"人物散步",
reference_images=["https://img/portrait.jpg"],
pre_trusted_images=["https://ai.example.com/t2i-portrait.png"],
duration=5,
ratio="9:16",
output_dir=str(tmp_path),
)
assert out is not None
# 只有一次 Seedance 创建任务(预热已完成,不再现场跑 Seedream)
assert len(captured) == 1
seedance_payload = captured[0]["json"]
content = seedance_payload["content"]
img_items = [c for c in content if c.get("type") == "image_url"]
assert len(img_items) == 1
# 不传 image_url,信任链产物放 ref_imgs,走 reference_image 模式(非 first_frame)
assert img_items[0]["image_url"]["url"] == "https://ai.example.com/t2i-portrait.png"
assert img_items[0]["role"] == "reference_image"
# 因为没有 image_url,没有 text 也没有 extra_refs 之外的字段,应保留用户 ratio=9:16
assert seedance_payload.get("ratio") == "9:16"
def test_image_generation_generic_exception_retries_then_fails(self):
"""image_generation 遇到非 HTTPStatusError 的通用异常时走重试分支(lines 962-971),重试耗尽后返回 None。"""
client = _make_client(max_retries=1)
call_n = {"n": 0}
def fake_post(url, **kw):
call_n["n"] += 1
if call_n["n"] == 1:
raise RuntimeError("boiler exploded")
# 第二次调用返回成功,验证重试生效
ok = MagicMock(status_code=200, text="")
ok.json.return_value = {"data": [{"url": "https://ai.example.com/retry-ok.png"}]}
ok.raise_for_status = MagicMock()
return ok
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.time.sleep", return_value=None),
):
r = client.image_generation("test prompt")
assert r is not None
assert r["url"] == "https://ai.example.com/retry-ok.png"
assert call_n["n"] == 2
def test_image_generation_generic_exception_exhausts_retries(self):
"""通用异常重试耗尽后返回 None,并正确写入 last_image_error (lines 969-971 break 分支)。"""
client = _make_client(max_retries=1)
def fake_post(url, **kw):
raise RuntimeError("always fails")
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.time.sleep", return_value=None),
):
r = client.image_generation("test prompt")
assert r is None
err = client.last_image_error
assert err["error_code"] == "network_error"
assert "always fails" in err["detail"]
+121 -1
View File
@@ -17,8 +17,13 @@ def _make_client(**overrides):
client.base_url = overrides.get("base_url", "https://ark.cn-beijing.volces.com/api/v3")
client.model = "doubao-model"
client.vision_model = "doubao-vision"
client.embedding_model = "doubao-embedding"
client.image_model = overrides.get("image_model", "doubao-seedream-5-0-pro-260628")
client.image_timeout = overrides.get("image_timeout", 120)
client.timeout = overrides.get("timeout", 30)
client.max_retries = overrides.get("max_retries", 0)
client.last_video_error = {}
client.last_image_error = {}
return client
@@ -106,7 +111,7 @@ class TestVideoGenerationHappyPath:
)
out = client.video_generation(
prompt=" 镜头一 ",
image_url="https://img/x.jpg",
# 不传 image_url:纯文生视频,不触发信任链,post 调用数为 1(创建任务)
duration=5,
ratio="9:16",
resolution="720p",
@@ -556,3 +561,118 @@ class TestResolveVideoModelId:
# 未知 model key 会通过 get_viral_video_model_config 回落到 seedance-2.5
with caplog.at_level(logging.WARNING, logger="shared.ai_client"):
assert fn("some-random-model") == "doubao-seedance-2-5-260628"
# ── #2165 详细错误信息和 last_video_error ─────────────────────────
class TestVideoGenerationLastError:
def test_create_400_portrait_returns_user_message(self, tmp_path):
"""#2169: HTTP 400 + 真人拦截关键词 → 自动尝试即梦兜底;即梦未配时返回 portrait_intercept。"""
client = _make_client(max_retries=0)
create_resp = MagicMock()
create_resp.status_code = 400
create_resp.text = '{"error":{"code":"ContentRisk","message":"Real person face detected in reference image, portrait blocked"}}'
create_resp.json.return_value = {"error": {"code": "ContentRisk", "message": "..."}}
create_resp.raise_for_status.side_effect = httpx.HTTPStatusError(
"bad", request=MagicMock(), response=create_resp
)
# 信任链:Seedream 会先被调用来 AI 化;这里 mock Seedream 也失败,回退原图直传,
# 原图直传被 400 portrait 拦截,最终返回 portrait_intercept。
seedream_resp = MagicMock()
seedream_resp.status_code = 400
seedream_resp.text = '{"error":{"code":"ContentRisk","message":"sensitive"}}'
seedream_resp.json.return_value = {"error": {"code": "ContentRisk", "message": "sensitive"}}
seedream_resp.raise_for_status.side_effect = httpx.HTTPStatusError(
"bad", request=MagicMock(), response=seedream_resp
)
def fake_post(url, **kwargs):
# 第一次 POST 是 Seedream(/images/generations),返回 portrait 拦截
# 回退原图直传后第二次 POST 是 Seedance(/contents/generations/tasks),也返回 portrait 拦截
return create_resp
with (
patch("packages.shared.ai_client.httpx.post", side_effect=fake_post),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.get_shared_settings") as mock_s,
):
mock_s.return_value = MagicMock(
doubao_video_poll_interval=0, doubao_video_timeout=1, doubao_video_model="seedance"
)
result = client.video_generation("p", output_dir=str(tmp_path), image_url="https://img/x.jpg")
assert result is None
err = client.get_last_video_error()
assert err["error_code"] == "portrait_intercept"
assert "真人" in err["user_message"] or "肖像" in err["user_message"] or "审核" in err["user_message"]
assert err["status_code"] in (0, 400)
def test_create_401_returns_auth_error(self, tmp_path):
client = _make_client(max_retries=0)
create_resp = MagicMock()
create_resp.status_code = 401
create_resp.text = '{"error":{"message":"Unauthorized"}}'
create_resp.json.return_value = {"error": {"message": "Unauthorized"}}
create_resp.raise_for_status.side_effect = httpx.HTTPStatusError(
"auth", request=MagicMock(), response=create_resp
)
with (
patch("packages.shared.ai_client.httpx.post", return_value=create_resp),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.get_shared_settings") as mock_s,
):
mock_s.return_value = MagicMock(
doubao_video_poll_interval=0, doubao_video_timeout=1, doubao_video_model="seedance"
)
result = client.video_generation("p", output_dir=str(tmp_path))
assert result is None
err = client.get_last_video_error()
assert err["error_code"] == "auth_error"
assert err["status_code"] == 401
def test_poll_failed_returns_task_failed_error(self, tmp_path):
"""轮询 status=failed 时应记录 task_failed 错误并含 detail。"""
client = _make_client(max_retries=0)
create_resp = MagicMock()
create_resp.status_code = 200
create_resp.json.return_value = {"id": "t-fail"}
create_resp.raise_for_status = MagicMock()
poll_resp = MagicMock()
poll_resp.status_code = 200
poll_resp.json.return_value = {
"status": "failed",
"error": {"code": "InvalidParam", "message": "resolution invalid"},
}
poll_resp.raise_for_status = MagicMock()
with (
patch("packages.shared.ai_client.httpx.post", return_value=create_resp),
patch("packages.shared.ai_client.httpx.get", return_value=poll_resp),
patch("packages.shared.ai_client.time.sleep", return_value=None),
patch("packages.shared.ai_client.time.time", side_effect=_fake_time_factory()),
patch("packages.shared.ai_client.get_shared_settings") as mock_s,
):
mock_s.return_value = MagicMock(
doubao_video_poll_interval=0, doubao_video_timeout=10, doubao_video_model="seedance"
)
result = client.video_generation("p", output_dir=str(tmp_path))
assert result is None
err = client.get_last_video_error()
assert err["error_code"] == "task_failed"
assert "InvalidParam" in err.get("detail", "") or err["status_code"] == 200
class TestAiServiceLastVideoError:
def test_call_video_generation_returns_none_sets_error(self):
"""失败后 get_last_video_error 应返回结构化错误信息。"""
from packages.shared import ai_service
mock_client = MagicMock()
mock_client.is_available = True
mock_client.last_video_error = {"error_code": "unknown", "user_message": "test"}
mock_client.get_last_video_error.return_value = {"error_code": "unknown", "user_message": "test"}
mock_client.video_generation.return_value = None
with patch("packages.shared.ai_service.get_doubao_client", return_value=mock_client):
assert ai_service.call_video_generation("p") is None
err = ai_service.get_last_video_error()
assert err["error_code"] == "unknown"
assert "user_message" in err
+395
View File
@@ -0,0 +1,395 @@
"""AI Router 单元测试 — 23 cases covering routing/cache/fallback/client construction."""
from __future__ import annotations
import sys
import unittest
from dataclasses import dataclass
from typing import Optional
from unittest.mock import MagicMock, patch
# ── Pre-mock heavy import chain to avoid pulling in full app ──
_mock_config = MagicMock()
_mock_settings = MagicMock()
_mock_settings.doubao_model = "doubao-seed-2-1-pro-260915"
_mock_settings.doubao_fast_model = "doubao-seed-2-1-pro-260915"
_mock_settings.doubao_base_url = "https://ark.cn-beijing.volces.com/api/v3"
_mock_settings.doubao_api_key = "test-key"
_mock_settings.doubao_timeout = 45
_mock_settings.doubao_max_retries = 1
_mock_settings.doubao_image_model = "doubao-seedream-5-0-flash-260915"
_mock_settings.doubao_image_timeout = 60
_mock_settings.doubao_video_model = "doubao-seedance-2-5-260628"
_mock_settings.doubao_video_timeout = 600
_mock_settings.dashscope_api_key = "ds-key"
_mock_settings.cosyvoice_api_key = "cv-key"
_mock_settings.cosyvoice_base_url = "https://dashscope.aliyuncs.com/api/v1"
_mock_settings.cosyvoice_model = "cosyvoice-v3-flash"
_mock_settings.redis_url = "redis://localhost:6379/0"
_mock_settings.celery_broker_url = "redis://localhost:6379/0"
_mock_config.get_shared_settings.return_value = _mock_settings
# Prevent the full packages.shared from loading
for mod_name in list(sys.modules.keys()):
if "packages.shared" in mod_name and "ai_router" not in mod_name and "ai_config_version" not in mod_name:
pass # don't remove, just prevent new imports
# Direct import of our modules (bypassing __init__.py)
import importlib.util
import os
def _load_module_from_file(name, path):
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod
spec.loader.exec_module(mod)
return mod
# Load ai_config_version
_ai_config_version = _load_module_from_file(
"packages.shared.ai_config_version",
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "packages", "shared", "ai_config_version.py"),
)
# Patch get_shared_settings in the loaded module
_ai_config_version.get_shared_settings = lambda: _mock_settings
# Load ai_router - needs packages.shared.config to be available
sys.modules["packages.shared.config"] = MagicMock()
sys.modules["packages.shared.config"].get_shared_settings = lambda: _mock_settings
# Mock packages.shared.ai_client to avoid triggering packages.shared.__init__ chain
# (which fails on Python 3.10 due to datetime.UTC import in packages.domain)
_mock_ai_client = MagicMock()
class _FakeDoubaoClient:
"""Fake DoubaoClient for testing - mimics the real interface."""
def __init__(self, api_key="", base_url="", model="", timeout=0, max_retries=0,
max_tokens=None, temperature=None, extra_params=None, provider="volcengine"):
self.api_key = api_key
self.base_url = base_url
self.model = model
self.timeout = timeout
self.max_retries = max_retries
self.max_tokens = max_tokens
self.temperature = temperature
self.extra_params = extra_params or {}
self.provider = provider
self.vision_model = model
@property
def is_available(self):
return bool(self.api_key)
def chat_completion(self, messages, **kwargs):
return None
def vision_completion(self, messages, **kwargs):
return None
_mock_ai_client.DoubaoClient = _FakeDoubaoClient
sys.modules["packages.shared.ai_client"] = _mock_ai_client
_ai_router = _load_module_from_file(
"packages.shared.ai_router",
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "packages", "shared", "ai_router.py"),
)
class TestAIConfigVersion(unittest.TestCase):
"""Redis 版本号机制测试"""
@patch.object(_ai_config_version, "_get_redis_client")
def test_bump_version_success(self, mock_redis_fn):
mock_r = MagicMock()
mock_r.set.return_value = True
mock_redis_fn.return_value = mock_r
ver = _ai_config_version.bump_version()
self.assertTrue(ver)
self.assertTrue(ver.isdigit())
mock_r.set.assert_called_once()
@patch.object(_ai_config_version, "_get_redis_client")
def test_bump_version_redis_unavailable(self, mock_redis_fn):
mock_redis_fn.return_value = None
ver = _ai_config_version.bump_version()
self.assertEqual(ver, "")
@patch.object(_ai_config_version, "_get_redis_client")
def test_get_version_success(self, mock_redis_fn):
mock_r = MagicMock()
mock_r.get.return_value = "1234567890"
mock_redis_fn.return_value = mock_r
ver = _ai_config_version.get_version()
self.assertEqual(ver, "1234567890")
@patch.object(_ai_config_version, "_get_redis_client")
def test_get_version_redis_down(self, mock_redis_fn):
mock_redis_fn.return_value = None
ver = _ai_config_version.get_version()
self.assertIsNone(ver)
@patch.object(_ai_config_version, "_get_redis_client")
def test_get_version_exception(self, mock_redis_fn):
mock_r = MagicMock()
mock_r.get.side_effect = Exception("connection refused")
mock_redis_fn.return_value = mock_r
ver = _ai_config_version.get_version()
self.assertIsNone(ver)
class TestAIRouter(unittest.TestCase):
"""AIRouter 路由/缓存/fallback 测试"""
def setUp(self):
self.router = _ai_router.AIRouter()
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_capability_db_unavailable(self, mock_ver):
with patch.object(_ai_router, "_get_session", return_value=None):
cap = self.router.get_capability("intent_parsing")
self.assertIsNone(cap)
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_capability_from_db(self, mock_ver):
mock_session = MagicMock()
mock_row = MagicMock()
mock_row.capability_key = "intent_parsing"
mock_row.capability_name = "文案意图解析"
mock_row.timeout_seconds = 45
mock_row.max_retries = 1
mock_row.max_tokens = None
mock_row.temperature = None
mock_row.concurrency = 2
mock_row.extra_params = {}
mock_row.is_enabled = True
mock_row.pm_id = "model-1"
mock_row.pm_name = "豆包"
mock_row.pm_provider = "volcengine"
mock_row.pm_model_key = "doubao-seed-1-6-250615"
mock_row.pm_api_key = "test-key"
mock_row.pm_api_base = "https://ark.test.com"
mock_row.pm_api_version = None
mock_row.pm_status = "active"
mock_row.lm_id = None
mock_row.fm_id = None
mock_session.execute.return_value.first.return_value = mock_row
with patch.object(_ai_router, "_get_session", return_value=mock_session):
cap = self.router.get_capability("intent_parsing")
self.assertIsNotNone(cap)
self.assertEqual(cap.capability_key, "intent_parsing")
self.assertEqual(cap.primary_model.model_key, "doubao-seed-1-6-250615")
@patch.object(_ai_config_version, "get_version", side_effect=[None, "v2"])
def test_cache_invalidation_on_version_change(self, mock_ver):
with patch.object(self.router, "_load_from_db", return_value=None):
self.router.get_capability("test_key")
self.router._local_ver = "v1"
self.assertTrue(self.router._check_version())
@patch.object(_ai_config_version, "get_version", return_value="same_ver")
def test_cache_hit_same_version(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="volcengine", model_key="test-model",
api_key="key", api_base="https://test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="test", capability_name="test", primary_model=model,
lite_model=None, fallback_model=None, timeout_seconds=30,
max_retries=1, max_tokens=None, temperature=None, concurrency=2,
extra_params={}, is_enabled=True,
)
self.router._cache["test"] = cap
self.router._local_ver = "same_ver"
result = self.router.get_capability("test")
self.assertEqual(result, cap)
def test_invalidate_clears_cache(self):
self.router._cache["x"] = MagicMock()
self.router._local_ver = "v1"
self.router.invalidate()
self.assertEqual(len(self.router._cache), 0)
self.assertIsNone(self.router._local_ver)
@patch.object(_ai_router, "_get_session", return_value=None)
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_llm_client_fallback(self, mock_ver, mock_session):
_ai_router.get_shared_settings = lambda: _mock_settings
client = self.router.get_llm_client("intent_parsing")
self.assertIsNotNone(client)
self.assertEqual(client.model, "doubao-seed-2-1-pro-260915")
self.assertEqual(client.api_key, "test-key")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_llm_client_from_db(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="dashscope", model_key="qwen3.8-flash",
api_key="db-key", api_base="https://dashscope.test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="image_analysis", capability_name="图片分析",
primary_model=model, lite_model=None, fallback_model=None,
timeout_seconds=15, max_retries=1, max_tokens=350, temperature=0.1,
concurrency=2, extra_params={}, is_enabled=True,
)
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_llm_client("image_analysis")
self.assertIsNotNone(client)
self.assertEqual(client.model, "qwen3.8-flash")
self.assertEqual(client.provider, "dashscope")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_vision_client(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="dashscope", model_key="qwen3.8-flash",
api_key="key", api_base="https://dashscope.test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="image_analysis", capability_name="图片分析",
primary_model=model, lite_model=None, fallback_model=None,
timeout_seconds=15, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={}, is_enabled=True,
)
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_vision_client("image_analysis")
self.assertIsNotNone(client)
# #2220: vision client is now DoubaoClient with vision_completion
self.assertTrue(hasattr(client, "vision_completion"))
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_tts_client(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="dashscope", model_key="cosyvoice-v3-flash",
api_key="key", api_base="https://dashscope.test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="tts", capability_name="语音合成",
primary_model=model, lite_model=None, fallback_model=None,
timeout_seconds=60, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={}, is_enabled=True,
)
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_tts_client()
self.assertIsNotNone(client)
self.assertEqual(client.model, "cosyvoice-v3-flash")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_image_gen_client(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="volcengine", model_key="seedream-5.0-flash",
api_key="key", api_base="https://ark.test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="image_generation", capability_name="图片生成",
primary_model=model, lite_model=None, fallback_model=None,
timeout_seconds=60, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={"size": "1K"}, is_enabled=True,
)
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_image_gen_client()
self.assertIsNotNone(client)
self.assertEqual(client.model, "seedream-5.0-flash")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_get_video_gen_client(self, mock_ver):
model = _ai_router.ModelConfig(
id="m1", name="test", provider="volcengine", model_key="seedance-2.5",
api_key="key", api_base="https://ark.test.com", api_version=None, status="active",
)
cap = _ai_router.CapabilityConfig(
capability_key="video_generation", capability_name="视频生成",
primary_model=model, lite_model=None, fallback_model=None,
timeout_seconds=600, max_retries=1, max_tokens=None, temperature=None,
concurrency=1, extra_params={}, is_enabled=True,
)
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_video_gen_client()
self.assertIsNotNone(client)
self.assertEqual(client.model, "seedance-2.5")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_lite_variant_preference(self, mock_ver):
primary = _ai_router.ModelConfig(id="p1", name="pro", provider="volcengine", model_key="pro-model", api_key="k", api_base="u", api_version=None, status="active")
lite = _ai_router.ModelConfig(id="l1", name="lite", provider="volcengine", model_key="lite-model", api_key="k", api_base="u", api_version=None, status="active")
cap = _ai_router.CapabilityConfig(
capability_key="image_analysis", capability_name="图片分析",
primary_model=primary, lite_model=lite, fallback_model=None,
timeout_seconds=15, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={}, is_enabled=True,
)
model = self.router._get_model_or_fallback(cap, "lite")
self.assertEqual(model.model_key, "lite-model")
model_primary = self.router._get_model_or_fallback(cap, "primary")
self.assertEqual(model_primary.model_key, "pro-model")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_disabled_capability_returns_fallback(self, mock_ver):
cap = _ai_router.CapabilityConfig(
capability_key="test", capability_name="test",
primary_model=None, lite_model=None, fallback_model=None,
timeout_seconds=30, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={}, is_enabled=False,
)
_ai_router.get_shared_settings = lambda: _mock_settings
with patch.object(self.router, "get_capability", return_value=cap):
client = self.router.get_llm_client("test")
self.assertIsNotNone(client)
self.assertEqual(client.model, "doubao-seed-2-1-pro-260915")
@patch.object(_ai_config_version, "get_version", return_value=None)
def test_fallback_chain_primary_none(self, mock_ver):
"""primary_model 为 None 时 fallback 到 fallback_model"""
fb = _ai_router.ModelConfig(id="f1", name="fb", provider="volcengine", model_key="fb-model", api_key="k", api_base="u", api_version=None, status="active")
cap = _ai_router.CapabilityConfig(
capability_key="test", capability_name="test",
primary_model=None, lite_model=None, fallback_model=fb,
timeout_seconds=30, max_retries=1, max_tokens=None, temperature=None,
concurrency=2, extra_params={}, is_enabled=True,
)
model = self.router._get_model_or_fallback(cap, "primary")
self.assertEqual(model.model_key, "fb-model")
class TestModelConfig(unittest.TestCase):
"""数据类测试"""
def test_model_config_frozen(self):
m = _ai_router.ModelConfig(id="1", name="t", provider="p", model_key="k", api_key="a", api_base="b", api_version=None, status="active")
with self.assertRaises(AttributeError):
m.model_key = "new"
def test_capability_config_frozen(self):
c = _ai_router.CapabilityConfig(
capability_key="k", capability_name="n", primary_model=None,
lite_model=None, fallback_model=None, timeout_seconds=30,
max_retries=1, max_tokens=None, temperature=None, concurrency=2,
extra_params={}, is_enabled=True,
)
with self.assertRaises(AttributeError):
c.is_enabled = False
class TestClientAvailability(unittest.TestCase):
"""客户端可用性测试"""
def test_tts_client_available(self):
c = _ai_router.TTSClient(provider="p", api_key="k", base_url="u", model="m")
self.assertTrue(c.is_available)
def test_tts_client_unavailable_no_model(self):
c = _ai_router.TTSClient(provider="p", api_key="k", base_url="u", model="")
self.assertFalse(c.is_available)
def test_image_gen_client_unavailable_no_url(self):
c = _ai_router.ImageGenClient(provider="p", api_key="k", base_url="", model="m")
self.assertFalse(c.is_available)
def test_video_gen_client_available(self):
c = _ai_router.VideoGenClient(provider="p", api_key="k", base_url="u", model="m")
self.assertTrue(c.is_available)
if __name__ == "__main__":
unittest.main()
+5 -5
View File
@@ -73,15 +73,15 @@ class TestSharedSettingsDefaults:
def test_default_cosyvoice_settings(self):
s = SharedSettings()
assert s.cosyvoice_model == "cosyvoice-v3-flash"
assert s.cosyvoice_model == "" # 零硬编码:默认值已清空
assert s.cosyvoice_format == "mp3"
assert s.cosyvoice_sample_rate == 22050
def test_default_doubao_settings(self):
s = SharedSettings()
assert "doubao" in s.doubao_model
assert s.doubao_timeout == 30
assert s.doubao_max_retries == 2
assert s.doubao_model == "" # 零硬编码:默认值已清空
assert s.doubao_timeout == 45 # #2180 默认提到45s
assert s.doubao_max_retries == 3
class TestAPISettingsDefaults:
@@ -321,7 +321,7 @@ class TestWorkerSettingsDefaults:
assert s.database_url # 继承自SharedSettings
assert s.redis_url
assert s.oss_endpoint
assert s.cosyvoice_model == "cosyvoice-v3-flash"
assert s.cosyvoice_model == "" # 零硬编码:默认值已清空
class TestGetWorkerSettings:
+198
View File
@@ -0,0 +1,198 @@
"""catalog 应用服务单测:会员套餐 / 积分包从共享库读取与字段映射。"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import pytest
@pytest.fixture(autouse=True)
def _clear_cache():
from packages.application.catalog import admin_catalog
admin_catalog._cache.clear()
yield
admin_catalog._cache.clear()
def _row(**kw):
row = MagicMock()
for k, v in kw.items():
setattr(row, k, v)
return row
class TestMembershipPlans:
def test_yearly_plan_mapping(self):
from packages.application.catalog import admin_catalog
row = _row(
plan_key="premium_yearly",
name="高级会员年卡",
description="年度订阅",
monthly_price=0,
yearly_price=399,
quotas={"4k": True, "batch_render": True, "credits_per_month": 500},
display_order=1,
)
session = MagicMock()
session.execute.return_value.fetchall.return_value = [row]
sl = MagicMock(return_value=session)
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", sl, create=True):
plans = admin_catalog.get_membership_plans()
assert len(plans) == 1
p = plans[0]
assert p["plan_id"] == "premium_yearly"
assert p["billing_cycle"] == "yearly"
assert p["price_cents"] == 39900
assert p["monthly_price_cents"] == 3325
assert p["duration_days"] == 365
assert p["features"]["4K 超清分辨率"] is True
assert p["features"]["credits_per_month"] == 500
session.close.assert_called_once()
def test_monthly_plan_mapping(self):
from packages.application.catalog import admin_catalog
row = _row(
plan_key="premium_monthly",
name="高级会员月卡",
description=None,
monthly_price=39,
yearly_price=0,
quotas=None,
display_order=2,
)
session = MagicMock()
session.execute.return_value.fetchall.return_value = [row]
sl = MagicMock(return_value=session)
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", sl, create=True):
plans = admin_catalog.get_membership_plans()
assert len(plans) == 1
p = plans[0]
assert p["billing_cycle"] == "monthly"
assert p["price_cents"] == 3900
assert p["monthly_price_cents"] == 3900
assert p["duration_days"] == 30
assert p["features"] == {}
def test_both_cycles_expanded(self):
from packages.application.catalog import admin_catalog
row = _row(
plan_key="premium",
name="高级会员",
description=None,
monthly_price=39,
yearly_price=399,
quotas={},
display_order=1,
)
session = MagicMock()
session.execute.return_value.fetchall.return_value = [row]
sl = MagicMock(return_value=session)
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", sl, create=True):
plans = admin_catalog.get_membership_plans()
cycles = {p["billing_cycle"] for p in plans}
assert cycles == {"yearly", "monthly"}
def test_no_session_returns_empty(self):
from packages.application.catalog import admin_catalog
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", None, create=True):
assert admin_catalog.get_membership_plans() == []
class TestPointsPackages:
def test_package_mapping_with_bonus(self):
from packages.application.catalog import admin_catalog
row = _row(
package_key="pkg_100",
name="100元充值包",
price=100,
credits=1000,
bonus_credits=100,
is_recommended=True,
description="推荐",
sort_order=4,
)
session = MagicMock()
session.execute.return_value.fetchall.return_value = [row]
sl = MagicMock(return_value=session)
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", sl, create=True):
packages = admin_catalog.get_points_packages()
assert len(packages) == 1
pkg = packages[0]
assert pkg["code"] == "pkg_100"
assert pkg["points"] == 1100
assert pkg["price_cents"] == 10000
assert pkg["is_recommended"] is True
assert pkg["unit_price"] == "¥0.091/积分"
def test_zero_credits_unit_price_safe(self):
from packages.application.catalog import admin_catalog
row = _row(
package_key="pkg_0",
name="空包",
price=0,
credits=0,
bonus_credits=0,
is_recommended=False,
description=None,
sort_order=0,
)
session = MagicMock()
session.execute.return_value.fetchall.return_value = [row]
sl = MagicMock(return_value=session)
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", sl, create=True):
packages = admin_catalog.get_points_packages()
assert packages[0]["points"] == 0
assert packages[0]["price_cents"] == 0
assert packages[0]["unit_price"] == "¥0.000/积分"
def test_no_session_returns_empty(self):
from packages.application.catalog import admin_catalog
with patch("packages.adapters.sqlalchemy_impl.session.SessionLocal", None, create=True):
assert admin_catalog.get_points_packages() == []
class TestPackagesRoute:
def test_get_packages_route_returns_items(self):
from app.api.routes.points import get_packages
cu = MagicMock()
cu.user.member_type = None
rows = [
{
"code": "pkg_10",
"name": "10元充值包",
"points": 100,
"price_cents": 1000,
"unit_price": "¥0.100/积分",
}
]
with patch(
"packages.application.catalog.admin_catalog.get_points_packages",
return_value=rows,
):
resp = get_packages(current_user=cu)
assert len(resp.packages) == 1
item = resp.packages[0]
assert item.code == "pkg_10"
assert item.points == 100
assert item.price_cents == 1000
+5 -5
View File
@@ -102,17 +102,17 @@ class TestSharedSettingsDefaults:
def test_default_cosyvoice_config(self):
"""CosyVoice 默认配置"""
s = self._make_settings()
assert s.cosyvoice_model == "cosyvoice-v3-flash"
assert s.cosyvoice_model == "" # 零硬编码:默认值已清空
assert s.cosyvoice_sample_rate == 22050
assert s.cosyvoice_format == "mp3"
assert s.cosyvoice_clone_model == "voice-enrollment"
assert s.cosyvoice_clone_model == "" # 零硬编码:默认值已清空
def test_default_doubao_config(self):
"""豆包默认配置"""
s = self._make_settings()
assert s.doubao_timeout == 30
assert s.doubao_max_retries == 2
assert "volces.com" in s.doubao_base_url
assert s.doubao_timeout == 45 # #2180 默认提到45s
assert s.doubao_max_retries == 3
assert s.doubao_base_url == "" # 零硬编码:默认值已清空
def test_default_empty_api_keys(self):
"""API Key 默认空字符串"""
+50 -10
View File
@@ -27,7 +27,10 @@ def mock_client() -> MagicMock:
@pytest.fixture
def service(mock_client: MagicMock) -> CosyVoiceService:
"""Create CosyVoiceService with mocked HTTP client and config."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test-12345678"
settings.cosyvoice_base_url = "https://dashscope.aliyuncs.com/api/v1"
@@ -37,6 +40,7 @@ def service(mock_client: MagicMock) -> CosyVoiceService:
settings.cosyvoice_voice = "longxiaochun_v3"
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None # ai_router returns None in tests
svc = CosyVoiceService(http_client=mock_client)
svc.CLONE_POLL_INTERVAL = 0.001 # 加速测试
svc.RETRY_BACKOFF = 0.001
@@ -48,7 +52,10 @@ class TestInitConfig:
def test_base_url_with_old_text2audio_path_gets_normalized(self, mock_client: MagicMock) -> None:
"""旧版 base_url 带 text2audio 路径应自动修正."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test"
settings.cosyvoice_base_url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2audio"
@@ -58,12 +65,16 @@ class TestInitConfig:
settings.cosyvoice_voice = "test"
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(http_client=mock_client)
assert svc._base_url == "https://dashscope.aliyuncs.com/api/v1"
def test_custom_params_override_config(self, mock_client: MagicMock) -> None:
"""显式传入参数覆盖配置."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-config"
settings.cosyvoice_base_url = "https://config.example.com"
@@ -73,6 +84,7 @@ class TestInitConfig:
settings.cosyvoice_voice = "test"
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(
api_key="sk-custom",
base_url="https://custom.example.com/api/v1",
@@ -87,7 +99,10 @@ class TestInitConfig:
def test_context_manager(self, mock_client: MagicMock) -> None:
"""上下文管理器正常工作."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test"
@@ -105,6 +120,7 @@ class TestInitConfig:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(http_client=mock_client)
with svc as s:
assert s is svc
@@ -113,7 +129,10 @@ class TestInitConfig:
def test_owns_client_gets_closed(self) -> None:
"""自有client在close时被关闭."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test"
@@ -131,6 +150,7 @@ class TestInitConfig:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
with patch("packages.application.cosyvoice_service.httpx.Client") as mock_cls:
mock_instance = MagicMock()
mock_cls.return_value = mock_instance
@@ -173,7 +193,10 @@ class TestSubmitCloneTask:
def test_no_api_key_raises_auth_error(self, mock_client: MagicMock) -> None:
"""无API Key抛认证错误."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = ""
@@ -191,6 +214,7 @@ class TestSubmitCloneTask:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(http_client=mock_client)
with pytest.raises(CosyVoiceAuthError, match="API Key 未配置"):
svc.submit_clone_task(audio_url="https://example.com/audio.mp3")
@@ -258,7 +282,10 @@ class TestSubmitCloneTask:
def test_audio_url_signer_is_called(self, mock_client: MagicMock) -> None:
"""配置了audio_url_signer时会被调用预签名."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test"
@@ -276,6 +303,7 @@ class TestSubmitCloneTask:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
signer = MagicMock(return_value="https://signed.example.com/audio.mp3?token=xxx")
svc = CosyVoiceService(http_client=mock_client, audio_url_signer=signer)
@@ -297,7 +325,10 @@ class TestSubmitCloneTask:
def test_signer_failure_falls_back_to_original_url(self, mock_client: MagicMock) -> None:
"""预签名失败时回退到原始URL."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = "sk-test"
@@ -315,6 +346,7 @@ class TestSubmitCloneTask:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
signer = MagicMock(side_effect=RuntimeError("sign failed"))
svc = CosyVoiceService(http_client=mock_client, audio_url_signer=signer)
@@ -375,7 +407,10 @@ class TestQueryVoiceStatus:
def test_no_api_key_raises(self, mock_client: MagicMock) -> None:
"""无API Key抛认证错误."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = ""
@@ -393,6 +428,7 @@ class TestQueryVoiceStatus:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(http_client=mock_client)
with pytest.raises(CosyVoiceAuthError):
svc.query_voice_status("v1")
@@ -589,7 +625,10 @@ class TestSubmitSynthesizeTask:
def test_no_api_key_raises(self, mock_client: MagicMock) -> None:
"""无API Key抛认证错误."""
with patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings:
with (
patch("packages.application.cosyvoice_service.get_shared_settings") as mock_settings,
patch("packages.shared.ai_router.ai_router") as mock_router,
):
settings = MagicMock()
settings.cosyvoice_api_key = ""
@@ -607,6 +646,7 @@ class TestSubmitSynthesizeTask:
settings.cosyvoice_clone_model = "voice-enrollment"
mock_settings.return_value = settings
mock_router.get_tts_client.return_value = None
svc = CosyVoiceService(http_client=mock_client)
with pytest.raises(CosyVoiceAuthError):
svc.submit_synthesize_task(text="你好", voice_id="v1")
+19
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
from unittest.mock import MagicMock, mock_open, patch
import httpx
import pytest
_SINGLETON = "_DASHSCOPE_CLIENT_SINGLETON"
@@ -157,3 +158,21 @@ class TestDashScopeVideoGeneration:
c.video_generation(prompt=" ", duration=5, ratio="9:16", resolution="720p", output_dir="/tmp/videos")
is None
)
def test_create_400_sets_last_video_error(self, tmp_path):
"""创建任务 HTTP 400 时应写 last_video_error。"""
from packages.shared import dashscope_client as dc
dc._DASHSCOPE_CLIENT_SINGLETON = None
with patch.dict("os.environ", {"DASHSCOPE_API_KEY": "test-key"}):
c = dc.DashScopeClient()
r = MagicMock()
r.status_code = 401
r.text = '{"code":"InvalidApiKey","message":"bad key"}'
r.raise_for_status.side_effect = httpx.HTTPStatusError("auth", request=MagicMock(), response=r)
with patch.object(dc.httpx, "post", return_value=r), patch.object(dc, "time"):
out = c.video_generation("p", output_dir=str(tmp_path))
assert out is None
err = c.get_last_video_error()
assert err["error_code"] == "auth_error"
assert c.last_video_error is not None
+225
View File
@@ -0,0 +1,225 @@
"""Ditto LLM 情绪分析服务单元测试."""
from __future__ import annotations
import json
from unittest.mock import MagicMock, patch
import pytest
from packages.application.ditto_emotion_service import (
EMO_HAPPY,
EMO_NEUTRAL,
DittoEmotionService,
EmotionSegment,
_parse_emotion_json,
align_timeline_by_length,
align_timeline_by_timings,
split_sentences,
)
# ── 分句 ─────────────────────────────────────────────────────────
class TestSplitSentences:
def test_empty(self):
assert split_sentences("") == []
def test_single(self):
assert split_sentences("你好。") == ["你好。"]
def test_multi(self):
sents = split_sentences("大家好!今天给大家推荐一款超棒的产品。它真的很好用;不信你试试?")
assert len(sents) == 4
assert "大家好!" in sents[0]
def test_english_punct(self):
sents = split_sentences("Hello! How are you? I'm fine.")
assert len(sents) == 3
# ── JSON 解析 ────────────────────────────────────────────────────
class TestParseEmotionJson:
def test_valid(self):
raw = json.dumps([{"text": "你好", "emo": 4, "intensity": 0.2}])
segs = _parse_emotion_json(raw)
assert len(segs) == 1
assert segs[0].emo == 4
assert segs[0].intensity == 0.2
def test_markdown_wrapped(self):
raw = "```json\n" + json.dumps([{"text": "好", "emo": 3, "intensity": 0.5}]) + "\n```"
segs = _parse_emotion_json(raw)
assert len(segs) == 1
assert segs[0].emo == 3
def test_forbidden_emo_becomes_neutral(self):
raw = json.dumps([{"text": "怒", "emo": 0, "intensity": 0.8}])
segs = _parse_emotion_json(raw)
assert len(segs) == 1
assert segs[0].emo == EMO_NEUTRAL
def test_invalid_json(self):
assert _parse_emotion_json("not json") == []
def test_empty(self):
assert _parse_emotion_json("") == []
def test_intensity_clamp(self):
raw = json.dumps([{"text": "a", "emo": 3, "intensity": 1.5}])
segs = _parse_emotion_json(raw)
assert segs[0].intensity == 1.0
def test_missing_text_skipped(self):
raw = json.dumps([{"emo": 3, "intensity": 0.4}])
segs = _parse_emotion_json(raw)
assert len(segs) == 0
# ── 时间对齐(按字数比例)────────────────────────────────────────
class TestAlignTimelineByLength:
def test_basic(self):
segs = [
EmotionSegment("ab", EMO_NEUTRAL, 0.2),
EmotionSegment("cd", EMO_HAPPY, 0.5),
]
entries = align_timeline_by_length(segs, 4.0)
assert len(entries) == 2
assert entries[0].start == 0.0
assert entries[0].end == 2.0
assert entries[1].start == 2.0
assert entries[1].end == 4.0
assert entries[0].emo == EMO_NEUTRAL
assert entries[1].emo == EMO_HAPPY
def test_empty_segments(self):
assert align_timeline_by_length([], 5.0) == []
def test_zero_duration(self):
segs = [EmotionSegment("ab", EMO_NEUTRAL, 0.2)]
assert align_timeline_by_length(segs, 0) == []
def test_unequal_length(self):
segs = [
EmotionSegment("a" * 3, EMO_HAPPY, 0.5),
EmotionSegment("b" * 1, EMO_NEUTRAL, 0.2),
]
entries = align_timeline_by_length(segs, 4.0)
assert entries[0].end == 3.0
assert entries[1].start == 3.0
assert entries[1].end == 4.0
# ── 时间对齐(sentence_timings)──────────────────────────────────
class TestAlignTimelineByTimings:
def test_exact_match(self):
segs = [
EmotionSegment("hello", EMO_HAPPY, 0.4),
EmotionSegment("world", EMO_NEUTRAL, 0.2),
]
timings = [
{"start": 0.0, "end": 1.5},
{"start": 1.5, "end": 3.0},
]
entries = align_timeline_by_timings(segs, timings, 3.0)
assert len(entries) == 2
assert entries[0].start == 0.0
assert entries[0].end == 1.5
assert entries[1].start == 1.5
assert entries[1].end == 3.0
def test_length_mismatch_fallback(self):
segs = [EmotionSegment("hello", EMO_HAPPY, 0.4)]
timings = [{"start": 0, "end": 1}, {"start": 1, "end": 2}]
entries = align_timeline_by_timings(segs, timings, 2.0)
assert len(entries) == 1
assert entries[0].end == 2.0
# ── DittoEmotionService ──────────────────────────────────────────
def _make_service(enabled=True, model=None, temperature=0.1, timeout=10, max_tokens=1024, prompt=""):
s = MagicMock()
s.ditto_emotion_enabled = enabled
s.ditto_emotion_model = model or ""
s.ditto_emotion_temperature = temperature
s.ditto_emotion_timeout = timeout
s.ditto_emotion_max_tokens = max_tokens
s.ditto_emotion_cache_size = 100
s.ditto_emotion_prompt = prompt
return DittoEmotionService(settings=s)
class TestDittoEmotionService:
def test_disabled_returns_empty(self):
svc = _make_service(enabled=False)
assert svc.analyze("你好世界") == []
def test_empty_text_returns_empty(self):
svc = _make_service(enabled=True)
assert svc.analyze("") == []
def test_llm_success(self):
svc = _make_service(enabled=True)
fake_reply = json.dumps([{"text": "你好", "emo": 4, "intensity": 0.2}])
with patch.object(svc, "_call_llm", return_value=_parse_emotion_json(fake_reply)):
segs = svc.analyze("你好")
assert len(segs) == 1
assert segs[0].emo == 4
def test_cache_hit(self):
svc = _make_service(enabled=True)
fake_reply = json.dumps([{"text": "你好世界", "emo": 3, "intensity": 0.5}])
with patch.object(svc, "_call_llm", return_value=_parse_emotion_json(fake_reply)) as mock_call:
svc.analyze("你好世界")
svc.analyze("你好世界")
assert mock_call.call_count == 1
def test_build_timeline_empty_when_disabled(self):
svc = _make_service(enabled=False)
assert svc.build_timeline("test", 5.0) == ""
def test_build_timeline_returns_json(self):
svc = _make_service(enabled=True)
fake_reply = json.dumps(
[
{"text": "ab", "emo": 4, "intensity": 0.2},
{"text": "cd", "emo": 3, "intensity": 0.4},
]
)
with patch.object(svc, "_call_llm", return_value=_parse_emotion_json(fake_reply)):
result = svc.build_timeline("ab。cd。", 4.0)
data = json.loads(result)
assert len(data) == 2
assert data[0]["emo"] == 4
assert data[1]["emo"] == 3
def test_build_timeline_with_sentence_timings(self):
svc = _make_service(enabled=True)
fake_reply = json.dumps(
[
{"text": "hello", "emo": 3, "intensity": 0.4},
{"text": "world", "emo": 4, "intensity": 0.2},
]
)
timings = [
{"start": 0.0, "end": 1.0},
{"start": 1.0, "end": 3.0},
]
with patch.object(svc, "_call_llm", return_value=_parse_emotion_json(fake_reply)):
result = svc.build_timeline("hello world", 3.0, sentence_timings=timings)
data = json.loads(result)
assert data[0]["start"] == 0.0
assert data[0]["end"] == 1.0
assert data[1]["end"] == 3.0
class TestPromptLoading:
def test_default_prompt_contains_placeholder(self):
from packages.application.ditto_emotion_service import _load_default_prompt
prompt = _load_default_prompt()
assert "{文案}" in prompt
def test_config_prompt_override(self):
custom = "分析情绪: {文案}"
svc = _make_service(enabled=True, prompt=custom)
assert svc._get_prompt_template() == custom
+229
View File
@@ -0,0 +1,229 @@
"""Ditto 蚂蚁数字人客户端单元测试 — #2076."""
from __future__ import annotations
import time
from unittest.mock import MagicMock, patch
import httpx
import pytest
from packages.application.ditto_service import DittoClient, DittoError, DittoResult
class _FakeResponse:
def __init__(self, status_code=200, content=b"\x00\x01" * 1000, headers=None, text=""):
self.status_code = status_code
self.content = content
self.headers = headers or {}
self.text = text
def _make_client(base_url="http://ditto:8000", default_video_url="http://oss/tpl.mp4", max_retries=2, timeout=60):
with patch("packages.application.ditto_service.get_api_settings") as mock_settings:
s = MagicMock()
s.ditto_api_base_url = base_url
s.ditto_default_video_url = default_video_url
s.ditto_max_retries = max_retries
s.ditto_request_timeout = timeout
mock_settings.return_value = s
return DittoClient()
def test_is_configured_true():
c = _make_client()
assert c.is_configured is True
def test_is_configured_false_without_base():
c = _make_client(base_url="")
assert c.is_configured is False
def test_is_configured_false_without_template():
c = _make_client(default_video_url="")
assert c.is_configured is False
def test_health_ok():
c = _make_client()
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.get.return_value = _FakeResponse(200)
mock_cls.return_value.__enter__.return_value = client
assert c.health() is True
client.get.assert_called_once()
def test_health_fail_status():
c = _make_client()
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.get.return_value = _FakeResponse(500)
mock_cls.return_value.__enter__.return_value = client
assert c.health() is False
def test_health_network_error():
c = _make_client()
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.get.side_effect = httpx.ConnectError("fail")
mock_cls.return_value.__enter__.return_value = client
assert c.health() is False
def test_generate_missing_base():
c = _make_client(base_url="")
with pytest.raises(DittoError, match="DITTO_API_BASE_URL"):
c.generate(audio_url="http://x/a.mp3", script="你好")
def test_generate_missing_audio():
c = _make_client()
with pytest.raises(DittoError, match="audio_url"):
c.generate(audio_url="", script="你好")
def test_generate_success_with_headers():
c = _make_client(max_retries=0)
fake_resp = _FakeResponse(
status_code=200,
content=b"\x00" * 99999,
headers={"X-RTF": "0.35", "X-Frames": "125", "X-Time": "12.5"},
)
with patch("httpx.Client") as mock_cls, patch("time.monotonic", side_effect=[0, 1]):
client = MagicMock()
client.post.return_value = fake_resp
mock_cls.return_value.__enter__.return_value = client
result = c.generate(audio_url="http://x/a.mp3", script="你好")
assert isinstance(result, DittoResult)
assert len(result.video_bytes) == 99999
assert result.rtf == 0.35
assert result.frames == 125
assert result.elapsed_seconds == 12.5
def test_generate_uses_default_template_when_video_url_empty():
c = _make_client(max_retries=0)
fake_resp = _FakeResponse(200, b"1" * 99999)
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.post.return_value = fake_resp
mock_cls.return_value.__enter__.return_value = client
c.generate(audio_url="http://x/a.mp3", script="你好")
call_kwargs = client.post.call_args
payload = call_kwargs.kwargs.get("json") or call_kwargs[1].get("json")
assert payload["video_url"] == "http://oss/tpl.mp4"
assert payload["audio_url"] == "http://x/a.mp3"
assert payload["script"] == "你好"
assert payload["emo_global"] == 4
assert payload["use_script_emo"] is True
def test_generate_retries_on_429_then_success():
c = _make_client(max_retries=2)
busy = _FakeResponse(429, b"", text="busy")
ok = _FakeResponse(200, b"v" * 99999)
with patch("httpx.Client") as mock_cls, patch("time.sleep") as mock_sleep:
client = MagicMock()
client.post.side_effect = [busy, ok]
mock_cls.return_value.__enter__.return_value = client
result = c.generate(audio_url="http://x/a.mp3", script="你好")
assert len(result.video_bytes) == 99999
assert mock_sleep.called
assert client.post.call_count == 2
def test_generate_429_exhausted():
c = _make_client(max_retries=1)
with patch("httpx.Client") as mock_cls, patch("time.sleep"):
client = MagicMock()
client.post.return_value = _FakeResponse(429, b"", text="busy")
mock_cls.return_value.__enter__.return_value = client
with pytest.raises(DittoError, match="重试"):
c.generate(audio_url="http://x/a.mp3", script="你好")
def test_generate_400_no_retry():
c = _make_client(max_retries=2)
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.post.return_value = _FakeResponse(400, b"", text="bad request")
mock_cls.return_value.__enter__.return_value = client
with pytest.raises(DittoError, match="Ditto 返回 400"):
c.generate(audio_url="http://x/a.mp3", script="你好")
assert client.post.call_count == 1 # 400 不重试
def test_generate_small_response_raises():
c = _make_client(max_retries=0)
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.post.return_value = _FakeResponse(200, b"xx")
mock_cls.return_value.__enter__.return_value = client
with pytest.raises(DittoError) as exc_info:
c.generate(audio_url="http://x/a.mp3", script="你好")
assert exc_info.value.code == "EmptyResponse"
def test_generate_and_persist_uploads_to_storage():
c = _make_client(max_retries=0)
fake_resp = _FakeResponse(200, b"v" * 99999)
fake_storage = MagicMock()
fake_storage.upload_file.return_value = "http://oss/ditto/x.mp4"
with (
patch("httpx.Client") as mock_cls,
patch("packages.shared.storage.get_shared_storage_service", return_value=fake_storage),
):
client = MagicMock()
client.post.return_value = fake_resp
mock_cls.return_value.__enter__.return_value = client
result = c.generate_and_persist(job_id="j1", user_id="u1", audio_url="http://x/a.mp3", script="hi")
assert result.video_url == "http://oss/ditto/x.mp4"
fake_storage.upload_file.assert_called_once()
call_args = fake_storage.upload_file.call_args
assert call_args.args[1].startswith("ditto-output/u1/j1")
def test_empty_script_replaced_with_space():
c = _make_client(max_retries=0)
fake_resp = _FakeResponse(200, b"v" * 99999)
with patch("httpx.Client") as mock_cls:
client = MagicMock()
client.post.return_value = fake_resp
mock_cls.return_value.__enter__.return_value = client
c.generate(audio_url="http://x/a.mp3", script="")
payload = client.post.call_args.kwargs["json"]
assert payload["script"] == " "
def test_generate_network_error_fails_fast(monkeypatch):
"""网络不通(ConnectError)时不重试,直接快速抛 NetworkUnreachable,避免用户等5分钟"""
import httpx
from packages.application import ditto_service as ds_mod
calls = {"n": 0}
def _fake_post(self, url, json=None):
calls["n"] += 1
raise httpx.ConnectError("[Errno 113] No route to host")
monkeypatch.setattr(httpx.Client, "post", _fake_post)
client = _make_client(
base_url="http://100.76.80.23:8000",
default_video_url="http://oss/tpl.mp4",
max_retries=2,
timeout=120,
)
t0 = time.monotonic()
with pytest.raises(ds_mod.DittoError) as exc:
client.generate(audio_url="http://oss/a.wav", script="你好")
elapsed = time.monotonic() - t0
assert exc.value.code == "NetworkUnreachable"
assert calls["n"] == 1 # 不重试
assert elapsed < 5 # 快速失败<5秒
@@ -521,3 +521,81 @@ class TestIngestJob:
storage_key="k",
)
assert job.error_message == ""
class TestViralVideoResumeForRegenerate:
"""#2222: resume_from_image_analyzed 应支持 COPY_GENERATED/COMPLETED/FAILED 重新生成文案。"""
def test_regen_from_copy_generated_clears_old_copy(self):
from datetime import datetime, timezone
from packages.domain.viral_video import ViralVideoJob, ViralVideoStatus
job = ViralVideoJob(user_id="u1", images=["img1"])
# 模拟已经生成过文案和视频
job.status = ViralVideoStatus.COPY_GENERATED
job.copy_result = {"shots": [{"x": 1}], "voiceover_script": "旧文案"}
job.intent_result = {"intent": "旧意图"}
job.storyboard = [{"x": 1}]
job.generated_copy_text = "旧文案"
job.result_video_url = "http://old.mp4"
job.completed_at = datetime(2026, 10, 6, tzinfo=timezone.utc)
job.error_msg = ""
job.current_stage = "tts_generation"
job.phase_message = "TTS完成"
# 重新生成
job.resume_from_image_analyzed()
assert job.status == ViralVideoStatus.RUNNING
assert job.copy_result is None
assert job.intent_result is None
assert job.storyboard is None
assert job.generated_copy_text == ""
assert job.result_video_url == ""
assert job.completed_at is None
assert job.error_msg == ""
assert job.current_stage == ""
assert job.phase_message == ""
def test_regen_from_completed_clears_old_copy(self):
from packages.domain.viral_video import ViralVideoJob, ViralVideoStatus
job = ViralVideoJob(user_id="u1", images=["img1"])
job.status = ViralVideoStatus.COMPLETED
job.copy_result = {"shots": [], "voiceover_script": "xx"}
job.intent_result = {"intent": "x"}
job.result_video_url = "http://v.mp4"
job.resume_from_image_analyzed()
assert job.status == ViralVideoStatus.RUNNING
assert job.copy_result is None
assert job.intent_result is None
assert job.result_video_url == ""
def test_first_call_from_image_analyzed_keeps_fields(self):
"""首次进入(IMAGE_ANALYZED)不应清空任何已有的字段。"""
from packages.domain.viral_video import ViralVideoJob, ViralVideoStatus
job = ViralVideoJob(user_id="u1", images=["img1"])
job.status = ViralVideoStatus.IMAGE_ANALYZED
job.image_analysis = {"products": []}
job.industry = "美妆"
job.resume_from_image_analyzed()
assert job.status == ViralVideoStatus.RUNNING
assert job.image_analysis == {"products": []}
assert job.industry == "美妆"
def test_wait_user_confirm_rejected(self):
"""wait_user_confirm 中间状态应被拒绝(前端正在编辑/确认文案)。"""
import pytest
from packages.domain.viral_video import ViralVideoJob, ViralVideoStatus
job = ViralVideoJob(user_id="u1", images=["img1"])
job.status = ViralVideoStatus.WAIT_USER_CONFIRM
with pytest.raises(ValueError, match="Cannot resume"):
job.resume_from_image_analyzed()
+221
View File
@@ -0,0 +1,221 @@
"""功能计费改造测试:爆款读配置、对口型/智能剪辑预扣逻辑。
策略:
- 爆款:通过修改缓存中的 FeatureConfig(multiplier/model_pricing)验证价格随配置变化
- lip_sync / smart_edit:直接测 LipsyncService 的预扣/结算/退款辅助方法,
PointsService 用 mock,避免依赖真实积分账户。
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
import pytest
from packages.domain import feature_pricing_service as fps
from packages.domain.feature_pricing_service import FeatureConfig, refresh_feature_configs
@pytest.fixture(autouse=True)
def _reset_cache():
refresh_feature_configs()
yield
refresh_feature_configs()
def _seed_cache(configs: dict) -> None:
import time
fps._cache = (time.monotonic(), configs)
class TestViralVideoReadsConfig:
def test_multiplier_change_changes_price(self):
"""配置里 multiplier 改大后,爆款价格随之变大(证明不再读死常量)。"""
from packages.domain.points_rules import calculate_viral_video_credits
# 基线兜底
base = calculate_viral_video_credits(15, 1280, 720)
assert base == 29.68
fallback = fps._fallback_configs()
vv = fallback["viral_video"]
vv.profit_multiplier = 2.0
_seed_cache(fallback)
changed = calculate_viral_video_credits(15, 1280, 720)
assert changed > base
# 精确校验:video_cost 相同,仅系数从 1.3 → 2.0
_, bd = __import__(
"packages.domain.points_rules", fromlist=["calculate_viral_video_credits_with_breakdown"]
).calculate_viral_video_credits_with_breakdown(15, 1280, 720)
assert bd["profit_multiplier"] == 2.0
def test_model_price_from_config(self):
"""model_pricing 改单价后,token 成本按新单价计算。"""
from packages.domain.points_rules import calculate_viral_video_credits_with_breakdown
fallback = fps._fallback_configs()
vv = fallback["viral_video"]
# seedance-2.5/720p/false 从 70 改成 100
vv.model_pricing["seedance-2.5"]["720p"]["false"] = 100.0
_seed_cache(fallback)
_, bd = calculate_viral_video_credits_with_breakdown(15, 1280, 720)
assert bd["model_price"] == 100.0
def test_price_cap_from_config(self):
from packages.domain.points_rules import calculate_viral_video_credits_with_breakdown
fallback = fps._fallback_configs()
vv = fallback["viral_video"]
vv.price_cap = 5.0
_seed_cache(fallback)
credits, bd = calculate_viral_video_credits_with_breakdown(15, 1280, 720)
assert credits == 5.0
assert bd["price_cap"] == 5.0
def test_disabled_feature_returns_zero_credits(self):
"""功能 is_enabled=false 时计费函数返回 0(纯计费层语义)。"""
from packages.domain.points_rules import calculate_viral_video_credits_with_breakdown
fallback = fps._fallback_configs()
fallback["viral_video"].is_enabled = False
_seed_cache(fallback)
credits, bd = calculate_viral_video_credits_with_breakdown(15, 1280, 720)
assert credits == 0.0
assert bd["feature_enabled"] is False
assert bd["charged"] is False
class TestLipSyncPricing:
def _make_service(self):
from app.services.lipsync_service import LipsyncService
svc = LipsyncService.__new__(LipsyncService)
svc.db = MagicMock()
return svc
def _lip_cfg(self, **kw):
base = dict(
feature_key="lip_sync",
name="对口型",
is_enabled=True,
fixed_cost=0.1,
profit_multiplier=1.0,
dynamic_unit_cost=0.05,
billing_mode="per_second",
price_cap=0.0,
model_pricing={},
description="",
)
base.update(kw)
return FeatureConfig(**base)
def test_estimate_duration_from_script(self):
svc = self._make_service()
# 10 个字 / 5 = 2 秒,下限 1
assert svc._estimate_duration(script_text="一二三四五六七八九十") == 2.0
# 无任何信息 → 默认 10 秒
assert svc._estimate_duration() == 10.0
def test_calculate_lipsync_price_per_second(self):
_seed_cache({"lip_sync": self._lip_cfg()})
price, bd = fps.calculate_price("lip_sync", dynamic_cost=20.0 * 0.05)
# dynamic 1.0 + fixed 0.1 = 1.1
assert price == 1.1
assert bd["charged"] is True
def test_settle_refunds_overcharge(self):
"""实际时长短 → 只退不补,退还差额。"""
svc = self._make_service()
_seed_cache({"lip_sync": self._lip_cfg()})
job = MagicMock()
job.credits_prepaid = 2.0
job.credits_cost = 0.0 # 未结算
job.user_id = "u1"
job.credits_transaction_id = "txn-old"
with patch("packages.domain.points_service.PointsService") as MockPS:
inst = MockPS.return_value
inst.refund_points.return_value = {"success": True}
svc._settle_lip_sync(job, actual_duration=10.0)
# final: (10*0.05 + 0.1)*1.0 = 0.6;退 2.0-0.6=1.4
assert round(job.credits_cost, 2) == 0.6
inst.refund_points.assert_called_once()
kwargs = inst.refund_points.call_args.kwargs
assert kwargs["amount"] == 1.4
def test_settle_no_refund_when_longer(self):
"""首期只退不补:实际更贵不补扣。"""
svc = self._make_service()
_seed_cache({"lip_sync": self._lip_cfg()})
job = MagicMock()
job.credits_prepaid = 0.5
job.credits_cost = 0.0
with patch("packages.domain.points_service.PointsService") as MockPS:
inst = MockPS.return_value
svc._settle_lip_sync(job, actual_duration=60.0)
assert round(job.credits_cost, 2) > 0.5
inst.refund_points.assert_not_called()
def test_refund_on_failure_full(self):
svc = self._make_service()
job = MagicMock()
job.credits_prepaid = 3.0
job.credits_cost = 0.0
job.user_id = "u1"
job.credits_transaction_id = "t1"
with patch("packages.domain.points_service.PointsService") as MockPS:
inst = MockPS.return_value
inst.refund_points.return_value = {"success": True}
svc._refund_lip_sync(job)
kwargs = inst.refund_points.call_args.kwargs
assert kwargs["amount"] == 3.0
class TestSmartEditFixedPrice:
def test_fixed_price_formula(self):
"""首期固定价:dynamic=0,price=fixed*multiplier,cap 封顶。"""
cfg = FeatureConfig(
feature_key="smart_edit",
name="智能剪辑",
is_enabled=True,
fixed_cost=2.0,
profit_multiplier=1.5,
billing_mode="model_based",
price_cap=0.0,
)
_seed_cache({"smart_edit": cfg})
price, bd = fps.calculate_price("smart_edit", dynamic_cost=0.0)
# (0+2)*1.5 = 3.0
assert price == 3.0
assert bd["dynamic_cost"] == 0.0
def test_fixed_price_with_cap(self):
cfg = FeatureConfig(
feature_key="smart_edit",
is_enabled=True,
fixed_cost=10.0,
profit_multiplier=2.0,
price_cap=8.0,
)
_seed_cache({"smart_edit": cfg})
price, _ = fps.calculate_price("smart_edit", dynamic_cost=0.0)
assert price == 8.0
def test_disabled_smart_edit_free(self):
cfg = FeatureConfig(feature_key="smart_edit", is_enabled=False, fixed_cost=2.0)
_seed_cache({"smart_edit": cfg})
price, bd = fps.calculate_price("smart_edit", dynamic_cost=0.0)
assert price == 0.0
assert bd["charged"] is False
+235
View File
@@ -0,0 +1,235 @@
"""feature_pricing_service 单元测试。
覆盖:
- 300s TTL 内存缓存(命中不重复 load / 过期重新 load / refresh 强制刷新)
- calculate_price 公式 (dynamic+fixed)*multiplier、price_cap 封顶、round
- disabled / 未知 key 返回 0
- DB 异常 / 空表 → 内置兜底配置(爆款启用且价格与现状一致)
- lookup_model_price 嵌套/扁平结构与旧版回落语义
"""
from __future__ import annotations
import time
import pytest
from packages.domain import feature_pricing_service as fps
from packages.domain.feature_pricing_service import (
CACHE_TTL_SECONDS,
FeatureConfig,
calculate_price,
get_feature_config,
is_feature_enabled,
lookup_model_price,
refresh_feature_configs,
)
@pytest.fixture(autouse=True)
def _reset_cache():
"""每个用例前后清空模块缓存,避免相互污染。"""
refresh_feature_configs()
yield
refresh_feature_configs()
def _cfg(key="x", **kw) -> FeatureConfig:
base = dict(
feature_key=key,
name=key,
is_enabled=True,
fixed_cost=0.2,
profit_multiplier=2.0,
dynamic_unit_cost=0.0,
billing_mode="per_second",
price_cap=0.0,
model_pricing={},
description="",
)
base.update(kw)
return FeatureConfig(**base)
class TestCacheTTL:
def test_cache_hit_avoids_reload(self, monkeypatch):
"""TTL 内第二次读取不再调 _load_all。"""
calls = {"n": 0}
def fake_load():
calls["n"] += 1
return {"x": _cfg()}
monkeypatch.setattr(fps, "_load_all", fake_load)
get_feature_config("x")
get_feature_config("x")
get_feature_config("x")
assert calls["n"] == 1
def test_expired_cache_reloads(self, monkeypatch):
"""超过 TTL 后重新 load。"""
calls = {"n": 0}
def fake_load():
calls["n"] += 1
return {"x": _cfg()}
monkeypatch.setattr(fps, "_load_all", fake_load)
get_feature_config("x")
assert calls["n"] == 1
# 把缓存时间戳回拨到 TTL 之前
ts, data = fps._cache
fps._cache = (ts - CACHE_TTL_SECONDS - 1, data)
get_feature_config("x")
assert calls["n"] == 2
def test_refresh_forces_reload(self, monkeypatch):
calls = {"n": 0}
def fake_load():
calls["n"] += 1
return {"x": _cfg()}
monkeypatch.setattr(fps, "_load_all", fake_load)
get_feature_config("x")
refresh_feature_configs()
get_feature_config("x")
assert calls["n"] == 2
def test_ttl_constant_is_300(self):
assert CACHE_TTL_SECONDS == 300.0
class TestCalculatePrice:
def test_basic_formula(self, monkeypatch):
# (dynamic 1.0 + fixed 0.2) * 2.0 = 2.4
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(dynamic_unit_cost=1.0)})
price, bd = calculate_price("x", dynamic_cost=1.0)
assert price == 2.4
assert bd["dynamic_cost"] == 1.0
assert bd["fixed_cost"] == 0.2
assert bd["profit_multiplier"] == 2.0
assert bd["final_price"] == 2.4
assert bd["charged"] is True
def test_price_cap_clamps(self, monkeypatch):
# raw = (1+0.2)*2 = 2.4,cap=1.0 → 1.0
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(price_cap=1.0)})
price, bd = calculate_price("x", dynamic_cost=1.0)
assert price == 1.0
assert bd["price_cap"] == 1.0
def test_no_cap_keeps_raw(self, monkeypatch):
# cap=0 视为不封顶
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(price_cap=0.0)})
price, _ = calculate_price("x", dynamic_cost=1.0)
assert price == 2.4
def test_rounded_two_decimals(self, monkeypatch):
monkeypatch.setattr(
fps,
"_load_all",
lambda: {"x": _cfg(fixed_cost=0.1, profit_multiplier=1.0)},
)
price, _ = calculate_price("x", dynamic_cost=1.0 / 3.0)
# 0.3333... + 0.1 = 0.4333 → 0.43
assert price == 0.43
def test_negative_dynamic_treated_as_zero(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg()})
price, _ = calculate_price("x", dynamic_cost=-5.0)
# (0 + 0.2) * 2 = 0.4
assert price == 0.4
def test_disabled_returns_zero(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(is_enabled=False)})
price, bd = calculate_price("x", dynamic_cost=1.0)
assert price == 0.0
assert bd["is_enabled"] is False
assert bd["charged"] is False
def test_unknown_key_returns_zero(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg()})
price, bd = calculate_price("nope", dynamic_cost=1.0)
assert price == 0.0
assert bd["charged"] is False
class TestDBFailureFallback:
def test_load_exception_uses_fallback(self, monkeypatch):
def boom():
raise RuntimeError("table does not exist")
monkeypatch.setattr(fps, "_load_all", boom)
cfg = get_feature_config("viral_video")
assert cfg is not None
assert cfg.is_enabled is True
assert cfg.fixed_cost == 0.15
assert cfg.profit_multiplier == 1.3
def test_empty_table_uses_fallback(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {})
assert get_feature_config("viral_video").is_enabled is True
assert get_feature_config("lip_sync").is_enabled is False
assert get_feature_config("smart_edit").is_enabled is False
def test_fallback_viral_price_matches_current(self, monkeypatch):
"""兜底爆款价格与旧硬编码现状一致:seedance-2.5/720p/false=70。"""
monkeypatch.setattr(fps, "_load_all", lambda: {})
from packages.domain.points_rules import calculate_viral_video_credits
# 默认全局开关关闭,但纯计费函数价格照常算
assert calculate_viral_video_credits(15, 1280, 720) == 29.68
def test_db_row_overrides_fallback(self, monkeypatch):
monkeypatch.setattr(
fps,
"_load_all",
lambda: {"viral_video": _cfg("viral_video", fixed_cost=0.5, profit_multiplier=2.0, price_cap=50.0)},
)
cfg = get_feature_config("viral_video")
assert cfg.fixed_cost == 0.5
assert cfg.profit_multiplier == 2.0
assert cfg.price_cap == 50.0
class TestIsFeatureEnabled:
def test_disabled_feature(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(is_enabled=False)})
assert is_feature_enabled("x") is False
def test_global_switch_off_blocks_enabled_feature(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(is_enabled=True)})
monkeypatch.setattr(fps, "_global_points_enabled", lambda: False)
assert is_feature_enabled("x") is False
def test_both_switches_on(self, monkeypatch):
monkeypatch.setattr(fps, "_load_all", lambda: {"x": _cfg(is_enabled=True)})
monkeypatch.setattr(fps, "_global_points_enabled", lambda: True)
assert is_feature_enabled("x") is True
class TestLookupModelPrice:
NESTED = {
"seedance-2.5": {
"720p": {"false": 70.0, "true": 42.0},
},
"wan-3.0": {"480p": {"false": 0.3}},
}
def test_nested_exact_hit(self):
assert lookup_model_price(self.NESTED, "seedance-2.5", "720p", False) == 70.0
assert lookup_model_price(self.NESTED, "seedance-2.5", "720p", True) == 42.0
def test_missing_bool_key_returns_none(self):
# wan-3.0/480p 只有 false,请求 true → None(由调用方回落)
assert lookup_model_price(self.NESTED, "wan-3.0", "480p", True) is None
def test_unknown_model_returns_none(self):
assert lookup_model_price(self.NESTED, "nope", "720p", False) is None
def test_flat_structure(self):
flat = {"m|720p|false": 12.5}
assert lookup_model_price(flat, "m", "720p", False) == 12.5
assert lookup_model_price(flat, "m", "720p", True) is None
+36 -23
View File
@@ -173,33 +173,46 @@ class TestSubscriptionPlans:
_spec.loader.exec_module(_mod)
return _mod.list_membership_plans
def test_plans_endpoint_returns_three_tiers(self):
import os # noqa: F401 (used by _import_plans_fn)
def test_plans_endpoint_reads_admin_table(self):
"""/subscription/plans 改读管理后台 plans 表:返回 catalog 服务提供的真实档位。"""
list_membership_plans = self._import_plans_fn()
resp = list_membership_plans(current_user=_make_cu())
real_plan = {
"plan_id": "premium_yearly",
"billing_cycle": "yearly",
"name": "高级会员年卡",
"description": "高级会员年度订阅,享受全部功能",
"price_cents": 39900,
"monthly_price_cents": 3325,
"duration_days": 365,
"features": {
"4K 超清分辨率": True,
"批量渲染": True,
"优先处理队列": True,
"credits_per_month": 500,
},
}
with patch(
"packages.application.catalog.admin_catalog.get_membership_plans",
return_value=[real_plan],
):
resp = list_membership_plans(current_user=_make_cu())
plans = resp["plans"]
plan_ids = {p["plan_id"] for p in plans}
assert plan_ids == {"monthly", "quarterly", "yearly"}
for p in plans:
assert p["price_cents"] > 0
assert p["duration_days"] in (30, 90, 365)
assert 0 < p["points_discount"] <= 1.0
assert "max_resolution" in p["features"]
def test_longer_plans_cheaper_per_month(self):
import os # noqa: F401
assert len(plans) == 1
p0 = plans[0]
assert p0["plan_id"] == "premium_yearly"
assert p0["price_cents"] == 39900
assert p0["duration_days"] == 365
assert p0["features"]["4K 超清分辨率"] is True
def test_plans_endpoint_empty_when_all_disabled(self):
"""后台停用全部套餐时,用户端返回空列表。"""
list_membership_plans = self._import_plans_fn()
resp = list_membership_plans(current_user=_make_cu())
plans = resp["plans"]
monthly = next(p for p in plans if p["plan_id"] == "monthly")
quarterly = next(p for p in plans if p["plan_id"] == "quarterly")
yearly = next(p for p in plans if p["plan_id"] == "yearly")
assert monthly["monthly_price_cents"] == 1990
assert quarterly["monthly_price_cents"] < monthly["monthly_price_cents"]
assert yearly["monthly_price_cents"] < quarterly["monthly_price_cents"]
with patch(
"packages.application.catalog.admin_catalog.get_membership_plans",
return_value=[],
):
resp = list_membership_plans(current_user=_make_cu())
assert resp["plans"] == []
# ── P1-7: multiplier consistency ──────────────────────────────────────
+8 -2
View File
@@ -3,7 +3,7 @@
from __future__ import annotations
import os
from unittest.mock import patch
from unittest.mock import MagicMock, patch
import pytest
@@ -108,8 +108,14 @@ class TestGetTtsService:
def test_empty_env_falls_back_to_auto_detect(self):
"""环境变量为空时自动检测."""
with patch.dict(os.environ, {"TTS_PROVIDER": ""}):
with (
patch.dict(os.environ, {"TTS_PROVIDER": ""}),
patch("packages.shared.config.get_shared_settings") as mock_settings,
):
# 没有 cosyvoice_api_key 时应该用 mock
settings = MagicMock()
settings.cosyvoice_api_key = ""
mock_settings.return_value = settings
service = get_tts_service(None)
assert service.provider_name == "mock"
+70 -53
View File
@@ -350,6 +350,29 @@ class TestViralVideoRepository:
class TestViralVideoPipeline:
"""编排器流水线测试。"""
# v3 分镜 XML(copy_display_markdown + clips + voiceover_script)
V3_XML = """<copy_display_markdown>今天给大家分享一支很显白的口红。</copy_display_markdown>
<clips>
<clip image_index="0" time_range="0-5秒">
<voiceover>大家好,今天分享一款口红</voiceover>
<visual>近景平视,缓慢推镜</visual>
<action_details>手持口红特写</action_details>
<audio_bgm>轻快流行BGM</audio_bgm>
<transition>硬切</transition>
<reference_image_index>0</reference_image_index>
</clip>
<clip image_index="1" time_range="5-15秒">
<voiceover>颜色特别好看很显白</voiceover>
<visual>特写,固定镜头</visual>
<action_details>嘴唇涂抹特写</action_details>
<audio_bgm>轻快BGM继续</audio_bgm>
<transition>结束</transition>
<reference_image_index>1</reference_image_index>
</clip>
</clips>
<voiceover_script>大家好,今天分享一款口红。颜色特别好看很显白</voiceover_script>
<theme>口红分享</theme>"""
@pytest.fixture
def mock_job(self):
return ViralVideoJob(
@@ -364,23 +387,27 @@ class TestViralVideoPipeline:
video_ratio="9:16",
)
@patch("packages.shared.ai_service.call_vision")
@patch("apps.worker.worker_app.tasks.vision.analyze_images_v2")
def test_image_analysis_step(self, mock_vision, mock_job):
from apps.worker.worker_app.tasks.viral_video import _step_image_analysis
mock_vision.return_value = {"name": "口红", "features": ["持久", "滋润"]}
# 每张图返回一个 v8 5 字段结果
mock_vision.return_value = [
{"type": "product", "name": "口红", "brand": "", "has_person": False, "summary_markdown": "一支口红"},
{"type": "product", "name": "口红", "brand": "", "has_person": False, "summary_markdown": "口红特写"},
]
result = _step_image_analysis(mock_job)
assert "products" in result
assert len(result["products"]) == 2 # 两张图片
assert "images" in result
assert len(result["images"]) == 2 # 两张图片
@patch("packages.shared.ai_service.call_vision")
@patch("apps.worker.worker_app.tasks.vision.analyze_images_v2")
def test_image_analysis_fallback(self, mock_vision, mock_job):
from apps.worker.worker_app.tasks.viral_video import _step_image_analysis
# 模拟 call_vision 不存在
mock_vision.side_effect = ImportError("no module")
# v2 分析内部异常时,每图走兜底,仍返回 images 结构
mock_vision.side_effect = RuntimeError("vision unavailable")
result = _step_image_analysis(mock_job)
assert "products" in result
assert "images" in result
def test_video_analysis_no_reference(self, mock_job):
from apps.worker.worker_app.tasks.viral_video import _step_video_analysis
@@ -390,49 +417,40 @@ class TestViralVideoPipeline:
result = _step_video_analysis(mock_job)
assert result is None
@patch("packages.shared.ai_service.call_llm")
def test_intent_parsing(self, mock_llm, mock_job):
from apps.worker.worker_app.tasks.viral_video import _step_intent_parsing
def test_intent_parsing_step_removed(self, mock_job):
"""intent_parsing 已合并进脚本生成,不再作为独立步骤/函数存在。"""
import apps.worker.worker_app.tasks.viral_video as vv
mock_llm.return_value = {"intent": "推广口红", "tone": "活泼"}
result = _step_intent_parsing(mock_job, {"products": []})
assert "intent" in result
assert not hasattr(vv, "_step_intent_parsing")
@patch("packages.shared.ai_service.call_llm")
def test_script_generation_returns_copy_result(self, mock_llm, mock_job):
def test_script_generation_returns_copy_result(self, mock_job):
"""v1.6: _step_script_generation 返回 dict 形式的 CopyResult,含 voiceover_script + shots。"""
from apps.worker.worker_app.tasks.viral_video import _step_script_generation
from packages.shared.ai_router import ai_router
mock_llm.return_value = {
"overview": {"theme": "口红推荐", "total_duration": 15, "aspect_ratio": "9:16"},
"scene_and_lighting": "明亮化妆台,柔和自然光",
"shots": [
{
"time_range": "0-5秒",
"shot_type_angle_movement": "近景平视,缓慢推镜",
"scene_and_dialogue": "女主微笑展示口红:大家好,今天分享一款口红",
"action_details": "手持口红特写",
"audio_bgm": "轻快流行BGM",
"transition": "硬切",
"reference_image_index": 0,
},
{
"time_range": "5-15秒",
"shot_type_angle_movement": "特写,固定镜头",
"scene_and_dialogue": "涂抹口红:颜色特别好看很显白",
"action_details": "嘴唇涂抹特写",
"audio_bgm": "轻快BGM继续",
"transition": "结束",
"reference_image_index": 1,
},
],
"hard_constraints": ["无字幕无水印"],
"negative_prompts": ["字幕", "水印"],
"voiceover_script": "大家好,今天分享一款口红,颜色特别好看很显白。",
}
result = _step_script_generation(
mock_job, {"intent": "推广口红", "key_messages": [], "tone": "亲切"}, {"products": []}
)
class _FakeClient:
is_available = True
model = "fake-storyboard"
def __init__(self, xml: str):
self._xml = xml
def chat_completion(self, messages, **kwargs):
return self._xml
fake = _FakeClient(self.V3_XML)
orig_get = ai_router.get_llm_client
def _get(task, variant="primary"):
if task == "storyboard":
return fake
return orig_get(task, variant=variant)
ai_router.get_llm_client = _get # type: ignore
try:
result = _step_script_generation(mock_job, {"images": []})
finally:
ai_router.get_llm_client = orig_get # type: ignore
assert isinstance(result, dict)
assert "voiceover_script" in result
assert "shots" in result
@@ -452,12 +470,13 @@ class TestViralVideoPipeline:
assert result["voiceover_script"]
assert len(result["shots"]) >= 1
@patch("packages.shared.ai_service.call_llm")
def test_review_pass_v16(self, mock_llm, mock_job):
@patch("packages.application.viral_video.reviewer.Reviewer.review")
def test_review_pass_v16(self, mock_review, mock_job):
"""v1.6 _step_review 接收 copy_result dict。"""
from apps.worker.worker_app.tasks.viral_video import _step_review
from packages.application.viral_video.reviewer import ReviewIssue, ReviewResult
mock_llm.return_value = {"passed": True, "score": 90, "details": {}}
mock_review.return_value = ReviewResult(passed=True, score=90, issues=[], rewrite_suggestions=[])
cr = {"voiceover_script": "大家好", "shots": []}
result = _step_review(mock_job, cr)
assert result["passed"] is True
@@ -503,7 +522,6 @@ class TestPipelineIntegration:
@patch("apps.worker.worker_app.tasks.viral_video._step_tts")
@patch("apps.worker.worker_app.tasks.viral_video._step_review")
@patch("apps.worker.worker_app.tasks.viral_video._step_script_generation")
@patch("apps.worker.worker_app.tasks.viral_video._step_intent_parsing")
@patch("apps.worker.worker_app.tasks.viral_video._step_video_analysis")
@patch("apps.worker.worker_app.tasks.viral_video._step_image_analysis")
@patch("apps.worker.worker_app.tasks.viral_video._get_repo_and_job")
@@ -514,7 +532,6 @@ class TestPipelineIntegration:
mock_get_repo,
mock_img_analysis,
mock_video_analysis,
mock_intent,
mock_script,
mock_review,
mock_tts,
@@ -541,8 +558,6 @@ class TestPipelineIntegration:
mock_session = MagicMock()
mock_get_repo.return_value = (mock_session, mock_repo, job)
# v1.6: 如果没有 copy_result 会现场补生成
mock_intent.return_value = {"intent": "推广", "key_messages": [], "tone": "亲切"}
mock_script.return_value = {
"overview": {"theme": "口红", "total_duration": 15, "aspect_ratio": "9:16"},
"scene_and_lighting": "明亮化妆台",
@@ -555,6 +570,8 @@ class TestPipelineIntegration:
mock_review.return_value = {"passed": True, "score": 90}
mock_tts.return_value = None # TTS 失败也能走下去(Seedance generate_audio=True 会自己合成音效)
mock_tts_upload.return_value = None
# _run_render_pipeline 直接读 job.copy_result(#2218 守卫),需提前注入
job.copy_result = mock_script.return_value
mock_render.return_value = ("/tmp/video.mp4", {"completion_tokens": 1000000})
mock_upload.return_value = "https://oss.example.com/final.mp4"
@@ -0,0 +1,357 @@
"""#2040 爆款视频 Prompt 模板系统单测(v8/v3 叙述优先重构后)。
不真调豆包 API,全部用 FakeClient 注入;覆盖:
XML 标签解析 / 3 套模板纯文本(image_analysis/storyboard/review)/
loader 缓存热加载与回落 / 本地规则审核识别违规词夸大 /
各现存步 fallback / seed 幂等 / 负面词不出现。
注:intent_parsing、copy_fusion 两套模板及其独立步骤已在叙述优先重构中删除,
相关用例同步移除。
"""
from __future__ import annotations
import os
import sys
import pytest
import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
for p in [REPO_ROOT, os.path.join(REPO_ROOT, "apps/api"), os.path.join(REPO_ROOT, "apps/worker")]:
if p not in sys.path:
sys.path.insert(0, p)
from packages.application.viral_video import xml_parser as xp # noqa: E402
from packages.application.viral_video.generator import CopyGenerator # noqa: E402
from packages.application.viral_video.prompt_loader import ( # noqa: E402
get_template,
invalidate,
render_user_prompt,
)
from packages.application.viral_video.prompts import ( # noqa: E402
BANNED_PHRASES,
DEFAULT_TEMPLATES,
)
from packages.application.viral_video.reviewer import Reviewer # noqa: E402
IMAGE_XML = """<products>
<product name="大公鸡头油污净" features="红白瓶身" position="main" image_index="0"/>
</products>
<colors><color hex="#D32F2F" name="红色" coverage="0.4"/></colors>
<people has_person="false" count="0"/>
<mood>干净实用</mood>
<visible_text><text_item text="多功能油污净" position="瓶身"/></visible_text>
<scene>白底棚拍</scene>
<quality resolution="高清" lighting="柔和" composition="居中"/>
<key_selling_points><point>去油快</point><point>625ml大容量</point></key_selling_points>"""
STORYBOARD_XML = """<clips>
<clip image_index="0" transition="cut" zoom="null" duration_sec="3" bgm_note="日常">
<voice_text>这油污忍很久了</voice_text>
<subtitle_text>油污忍很久</subtitle_text>
<ken_burns start="0,0" end="0,0" ease="linear"/>
</clip>
<clip image_index="0" transition="zoom_in" zoom="in" duration_sec="10" bgm_note="轻快">
<voice_text>大公鸡头喷上等几分钟一擦就净</voice_text>
<subtitle_text>一擦就净</subtitle_text>
<ken_burns start="20,20" end="80,80" ease="ease-in-out"/>
</clip>
</clips>"""
REVIEW_FAIL_XML = """<passed>false</passed>
<issues><issue dimension="夸大承诺" severity="error" location="body_points">出现绝对化表述</issue></issues>
<rewrite_suggestions><suggestion>改为“大部分油污能擦掉”</suggestion></rewrite_suggestions>"""
REVIEW_PASS_XML = """<passed>true</passed>
<issues></issues>
<rewrite_suggestions></rewrite_suggestions>"""
class FakeClient:
"""按 system 内容路由 canned 响应的假豆包客户端。"""
def __init__(self):
self.chat_calls: list[list[dict]] = []
self.vision_calls: list = []
self.review_sequence: list[str] | None = None
def chat_completion(self, messages, **kwargs):
self.chat_calls.append(messages)
system = messages[0]["content"]
# v3 审核 prompt 关键短语(叙述优先重构后更新)
if "短视频广告合规审核与文案优化专家" in system:
if self.review_sequence:
return self.review_sequence.pop(0)
return REVIEW_PASS_XML
# v3 分镜 prompt
if "懂短视频的编导和口播文案高手" in system:
return STORYBOARD_XML
return ""
def vision_completion(self, messages, images=None, **kwargs):
self.vision_calls.append({"messages": messages, "images": images})
return IMAGE_XML
@pytest.fixture(autouse=True)
def _clear_loader():
invalidate()
yield
invalidate()
# ── XML 解析 ──────────────────────────────────────────────────────────────
class TestXmlParser:
def test_parse_paired_tags_and_attrs(self):
nodes = xp.find_all(IMAGE_XML, "product")
assert len(nodes) == 1
assert nodes[0]["attrs"]["name"] == "大公鸡头油污净"
assert nodes[0]["attrs"]["image_index"] == "0"
def test_parse_selling_points(self):
points = [n["text"] for n in xp.find_all(IMAGE_XML, "point")]
assert points == ["去油快", "625ml大容量"]
def test_self_closing_and_bool_helpers(self):
nodes = xp.parse_tags('<people has_person="false"/><done x="true"/>')
assert xp.attr_bool(nodes[0]["attrs"]["has_person"]) is False
assert xp.attr_bool(nodes[1]["attrs"]["x"]) is True
assert xp.attr_float("0.97") == pytest.approx(0.97)
assert xp.attr_int("13", 5) == 13
def test_malformed_text_safe(self):
assert xp.find_all(None, "tag") == []
assert xp.text_of("乱七八糟没有标签", "intent", "默认") == "默认"
# ── 3 套模板纯文本 ────────────────────────────────────────────────────────
class TestTemplates:
def test_three_templates_present(self):
types_ = {t["prompt_type"] for t in DEFAULT_TEMPLATES}
assert types_ == {"image_analysis", "storyboard", "review"}
def test_no_json_blocks_in_templates(self):
for template in DEFAULT_TEMPLATES:
blob = "\n".join([template["system_prompt"], template["user_prompt_template"], template["example_output"]])
# image_analysis 模板明确要求输出 JSON,故只对非 image_analysis 模板校验
if template["prompt_type"] != "image_analysis":
assert "```json" not in blob
assert "JSON schema" not in blob
def test_placeholders_render_and_missing_key_kept(self):
# 现存模板里选取 storyboard 做占位符渲染校验
template = get_template("storyboard")
rendered = render_user_prompt(template, marketing_purpose="去油快", industry="家居")
assert "去油快" in rendered
# ── loader:DB 加载/缓存/回落 ─────────────────────────────────────────────
class TestPromptLoader:
def test_fallback_when_session_none(self, monkeypatch):
import packages.adapters.sqlalchemy_impl.session as session_mod
monkeypatch.setattr(session_mod, "SessionLocal", None, raising=False)
template = get_template("review")
assert template is not None
# v3 审核 prompt 实际内容断言
assert "合规审核" in template.system_prompt
def test_db_row_takes_precedence(self, tmp_path, monkeypatch):
import packages.adapters.sqlalchemy_impl.session as session_mod
db_path = tmp_path / "t.db"
engine = sa.create_engine(f"sqlite:///{db_path}")
with engine.begin() as conn:
conn.execute(
sa.text(
"CREATE TABLE viral_video_prompt_templates ("
"id INTEGER PRIMARY KEY, name TEXT, prompt_type TEXT, version INTEGER,"
"system_prompt TEXT, user_prompt_template TEXT, example_output TEXT,"
"is_active INTEGER)"
)
)
conn.execute(
sa.text(
"INSERT INTO viral_video_prompt_templates VALUES"
"(1,'自定义','review',2,'DB里的系统提示','DB用户提示','',1)"
)
)
factory = sessionmaker(bind=engine)
monkeypatch.setattr(session_mod, "SessionLocal", factory, raising=False)
template = get_template("review", force_refresh=True)
assert template.system_prompt == "DB里的系统提示"
assert template.version == 2
# 改 DB 后 30 秒内仍走缓存
with engine.begin() as conn:
conn.execute(sa.text("UPDATE viral_video_prompt_templates SET system_prompt='改了' WHERE id=1"))
assert get_template("review").system_prompt == "DB里的系统提示"
# force_refresh 后热加载生效
assert get_template("review", force_refresh=True).system_prompt == "改了"
def test_invalid_type_raises(self):
with pytest.raises(ValueError):
get_template("not_exist")
# ── 现存步编排与 fallback ────────────────────────────────────────────────
class TestGenerator:
def test_image_fallback_on_garbage(self):
client = FakeClient()
client.vision_completion = lambda *a, **k: "完全无法解析的内容" # type: ignore
gen = CopyGenerator(client=client)
analysis = gen.analyze_images(["https://x/1.jpg"])
assert analysis.products[0].name.startswith("无法判断")
def test_storyboard_fallback_on_garbage(self):
client = FakeClient()
client.chat_completion = lambda *a, **k: "啥都没有" # type: ignore
gen = CopyGenerator(client=client)
from packages.application.viral_video.schemas import FusionResult, ScriptSegment
fusion = FusionResult(
hook="开头",
script_segments=[ScriptSegment(text="a", duration_sec=5), ScriptSegment(text="b", duration_sec=5)],
)
board = gen.storyboard(fusion, None, ["u"], 10)
assert len(board.clips) == 2
assert board.clips[0].voice_text == "a"
# ── 审核本地规则(LLM 降级放行时本地规则仍应识别红线)────────────────────
class TestReview:
def test_rule_check_catches_exaggeration_even_if_llm_passes(self):
client = FakeClient() # LLM 默认返回 passed
reviewer = Reviewer(client=client)
from packages.application.viral_video.schemas import FusionResult, IntentResult
fusion = FusionResult(title="一喷100%掉光", hook="x", cta="买")
result = reviewer.review(fusion, IntentResult(), "ai_full")
# LLM 返回 passed,且本地规则命中夸大 → 整体不通过
assert result.passed is False
dims = {i.dimension for i in result.issues}
assert "夸大承诺" in dims
def test_rule_check_catches_banned_phrase(self):
client = FakeClient()
reviewer = Reviewer(client=client)
from packages.application.viral_video.schemas import FusionResult
fusion = FusionResult(title="绝绝子", hook="x", cta="买")
result = reviewer.review(fusion, None, "ai_full")
assert not result.passed
assert any("绝绝子" in i.text for i in result.issues)
def test_missing_personal_brand_flagged(self):
client = FakeClient()
reviewer = Reviewer(client=client)
from packages.application.viral_video.schemas import (
FusionResult,
IntentResult,
PersonalBrand,
)
fusion = FusionResult(title="合规标题", hook="钩子", cta="行动")
intent = IntentResult(personal_brands=[PersonalBrand(text="39块钱一瓶", category="price")])
result = reviewer.review(fusion, intent, "ai_polish")
assert not result.passed
assert any("39块钱一瓶" in i.text and i.dimension == "事实一致性" for i in result.issues)
def test_missing_core_message_flagged(self):
client = FakeClient()
reviewer = Reviewer(client=client)
from packages.application.viral_video.schemas import (
CoreMessage,
FusionResult,
IntentResult,
)
fusion = FusionResult(title="标题", hook="别的内容", cta="号召")
intent = IntentResult(core_messages=[CoreMessage(text="必须保留的原意", must_keep=True)])
result = reviewer.review(fusion, intent, "user_primary")
assert any(i.dimension == "用户意图保留" for i in result.issues)
def test_rule_fix_local(self):
reviewer = Reviewer(client=FakeClient())
from packages.application.viral_video.schemas import (
BodyPoint,
FusionResult,
ReviewIssue,
ReviewResult,
)
fusion = FusionResult(
title="一喷100%掉光",
hook="绝绝子",
cta="最好用",
body_points=[BodyPoint(text="立刻见效")],
)
review = ReviewResult(
passed=False,
issues=[ReviewIssue(dimension="夸大承诺", text="100%")],
)
fixed = reviewer._rule_fix(fusion, review)
assert "100%" not in fixed.title
assert fixed.hook == ""
assert fixed.cta == "很不错用"
assert fixed.body_points[0].text == "坚持使用会有改善"
# ── seed 幂等 ─────────────────────────────────────────────────────────────
class TestSeed:
def test_seed_idempotent(self, tmp_path):
scripts_dir = os.path.join(REPO_ROOT, "scripts")
sys.path.insert(0, scripts_dir)
import importlib
seed_mod = importlib.import_module("seed_viral_video_prompts")
db_path = tmp_path / "seed.db"
engine = sa.create_engine(f"sqlite:///{db_path}")
with engine.begin() as conn:
conn.execute(
sa.text(
"CREATE TABLE viral_video_prompt_templates ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, prompt_type TEXT,"
"version INTEGER, system_prompt TEXT, user_prompt_template TEXT,"
"example_output TEXT, is_active INTEGER DEFAULT 1,"
"created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,"
"updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,"
"UNIQUE(prompt_type, version))"
)
)
assert seed_mod.seed(engine) == 3
assert seed_mod.seed(engine) == 3 # 再来一次不报错
with engine.begin() as conn:
count = conn.execute(sa.text("SELECT COUNT(*) FROM viral_video_prompt_templates")).scalar()
assert count == 3
with engine.begin() as conn:
types_ = {
r[0]
for r in conn.execute(sa.text("SELECT prompt_type FROM viral_video_prompt_templates WHERE is_active=1"))
}
assert types_ == {"image_analysis", "storyboard", "review"}
# ── 负面词不出现于程序产出 ────────────────────────────────────────────────
class TestNegativeOutput:
def test_fallback_outputs_clean(self):
gen = CopyGenerator(client=FakeClient())
from packages.application.viral_video.schemas import (
FusionResult,
ImageAnalysis,
IntentResult,
)
fusion = gen._fallback_fusion(
"ai_full",
ImageAnalysis(products=[]),
IntentResult(intent_summary="正常产品"),
15,
"",
)
blob = "\n".join(s.text for s in fusion.script_segments)
for phrase in BANNED_PHRASES:
assert phrase not in blob
+28 -2
View File
@@ -431,7 +431,7 @@ class TestGenerateCopy:
assert resp.id == "job-gc"
def test_generate_copy_rejects_wrong_status(self):
"""任务在 copy_generated/completed 时不能再 generate-copy(状态保护)。"""
"""wait_user_confirm 等中间状态不允许调用 generate-copy(状态保护)。"""
import pytest
from app.api.routes import viral_video as vv_mod
from app.schemas.viral_video import GenerateCopyRequest
@@ -441,7 +441,8 @@ class TestGenerateCopy:
user = _auth_user("u1")
session = MagicMock()
job = _make_job(job_id="job-gc2", user_id="u1", status=ViralVideoStatus.COPY_GENERATED)
# wait_user_confirm 属于前端在编辑/确认文案的中间状态,应拒绝重新触发生成
job = _make_job(job_id="job-gc2", user_id="u1", status=ViralVideoStatus.WAIT_USER_CONFIRM)
repo = MagicMock()
repo.get.return_value = job
@@ -450,6 +451,31 @@ class TestGenerateCopy:
vv_mod.generate_copy("job-gc2", GenerateCopyRequest(), authenticated_user=user, session=session)
assert exc.value.status_code == 409
def test_generate_copy_allows_regenerate_from_copy_generated(self):
"""#2222: COPY_GENERATED/COMPLETED 状态下点「重新生成文案」应放行入队,不返回 409。"""
from unittest.mock import patch
from app.api.routes import viral_video as vv_mod
from app.schemas.viral_video import GenerateCopyRequest
from packages.domain.viral_video import ViralVideoStatus
user = _auth_user("u1")
session = MagicMock()
for regen_status in (ViralVideoStatus.COPY_GENERATED, ViralVideoStatus.COMPLETED):
job = _make_job(job_id=f"job-regen-{regen_status}", user_id="u1", status=regen_status)
repo = MagicMock()
repo.get.return_value = job
with (
patch.object(vv_mod, "_get_job_repo", return_value=repo),
patch.object(vv_mod.celery_app, "send_task") as mock_send,
):
resp = vv_mod.generate_copy(f"job-regen-{regen_status}", GenerateCopyRequest(), authenticated_user=user, session=session)
mock_send.assert_called_once()
job.resume_from_image_analyzed.assert_called()
assert job.retry_count >= 1
assert resp.id == f"job-regen-{regen_status}"
def test_generate_copy_persists_voice_and_ratio(self):
"""generate-copy 应把 voice_id/voice_source/video_ratio 写入 job。"""
from unittest.mock import patch
+317
View File
@@ -0,0 +1,317 @@
"""#2040 接线集成测试(v8/v3 叙述优先重构后):
验证运行中的 viral_video 任务使用 prompt_loader 从 DB 读取模板。
mock LLM/Vision 调用,验证:
1. image_analysis 走 V2 批处理路径,输出 {"images": [...]}
2. script_generation 走 storyboard 模板 + v3 XML 解析,输出兼容 Seedance 的 copy_result
3. review 走 Reviewer(review 模板)带自动重写
4. 三档融合(ai_full / ai_polish / user_primary)的风格指令随 job.fusion_level 体现
注:intent_parsing 独立步骤已删除,相关用例同步移除。
"""
from __future__ import annotations
import sys
from pathlib import Path as _Path
_WORKER_ROOT = _Path(__file__).resolve().parents[2] / "apps" / "worker"
if str(_WORKER_ROOT) not in sys.path:
sys.path.insert(0, str(_WORKER_ROOT))
from unittest.mock import patch
import pytest
from packages.domain.viral_video import ViralVideoJob
@pytest.fixture
def job():
j = ViralVideoJob(
user_id="u1",
images=["https://img/1.jpg", "https://img/2.jpg"],
industry="美妆",
duration=15,
user_copy_text="这款口红真的显白又持久,姐妹们冲!",
fusion_level="ai_polish",
)
return j
# ── v3 分镜 XML(与新 storyboard 模板 schema 对齐)──────────────────
V3_XML = """<copy_display_markdown>今天给大家分享一支很显白的口红。</copy_display_markdown>
<clips>
<clip image_index="0" time_range="0-5秒">
<voiceover>大家好,今天分享一款口红</voiceover>
<visual>近景平视,缓慢推镜</visual>
<action_details>手持口红特写</action_details>
<audio_bgm>轻快流行BGM</audio_bgm>
<transition>硬切</transition>
<reference_image_index>0</reference_image_index>
</clip>
<clip image_index="1" time_range="5-15秒">
<voiceover>颜色特别好看很显白</voiceover>
<visual>特写,固定镜头</visual>
<action_details>嘴唇涂抹特写</action_details>
<audio_bgm>轻快BGM继续</audio_bgm>
<transition>结束</transition>
<reference_image_index>1</reference_image_index>
</clip>
</clips>
<voiceover_script>大家好,今天分享一款口红。颜色特别好看很显白</voiceover_script>
<theme>口红分享</theme>"""
@pytest.fixture(autouse=True)
def invalidate_loader_cache():
from packages.application.viral_video import prompt_loader as pl
pl.invalidate()
yield
pl.invalidate()
class _FakeClient:
"""替代 ai_router 返回的假 LLM 客户端,固定返回 v3 XML。"""
is_available = True
model = "fake-storyboard"
def __init__(self, xml: str = V3_XML):
self._xml = xml
self.captured: list[list[dict]] = []
def chat_completion(self, messages, **kwargs):
self.captured.append(messages)
return self._xml
@pytest.fixture
def patch_router(job):
"""把 ai_router 单例的 get_llm_client 替换为返回 _FakeClient。"""
from packages.shared.ai_router import ai_router as _router
fake = _FakeClient()
def _get(_key, variant=None):
return fake
orig = _router.get_llm_client
_router.get_llm_client = _get # type: ignore
job.image_analysis = {"images": []}
yield fake
_router.get_llm_client = orig # type: ignore
# ── 1) 图片分析走 V2 批处理 ──────────────────────────────────────────
class TestImageAnalysisWiring:
def test_step_image_analysis_uses_v2_batch_path(self, job):
"""图片分析走 V2 批处理,_step_image_analysis 归一化 URL 后调用 analyze_images_v2。"""
from apps.worker.worker_app.tasks import viral_video as vv
fake_image = {
"type": "product",
"name": "lipstick",
"brand": "品牌X",
"has_person": False,
"summary_markdown": "一支品牌X的红色口红。",
"_source": "v2",
}
with patch.object(vv, "_normalize_image_url", side_effect=lambda raw, idx: raw):
with patch(
"worker_app.tasks.vision.analyze_images_v2",
return_value=[fake_image, fake_image],
create=True,
) as mock_v2:
result = vv._step_image_analysis(job)
mock_v2.assert_called_once()
# 传入的是归一化后的图片 URL 列表
assert mock_v2.call_args.args[0] == job.images
images = result["images"]
assert len(images) == 2
assert images[0]["name"] == "lipstick"
assert images[0]["brand"] == "品牌X"
assert images[0]["type"] == "product"
assert images[0]["summary_markdown"] == "一支品牌X的红色口红。"
def test_step_image_analysis_empty_images(self, job):
from apps.worker.worker_app.tasks import viral_video as vv
job.images = []
result = vv._step_image_analysis(job)
assert result == {"images": []}
# ── 2) 脚本生成:storyboard 模板 + v3 XML 解析 + fusion_level ───────
class TestScriptGenerationWiring:
@pytest.mark.parametrize("level", ["ai_full", "ai_polish", "user_primary"])
def test_fusion_level_injected(self, job, patch_router, level):
"""不同 fusion_level 下脚本生成走通,输出 Seedance 兼容结构。
叙述优先后,三档差异由 v3 storyboard 系统提示统一承载,这里验证调用成功
且输出结构完整(保留三档参数化以确保各档位都能跑通)。
"""
from apps.worker.worker_app.tasks import viral_video as vv
job.fusion_level = level
result = vv._step_script_generation(job, {"images": []})
# 输出保持 Seedance 兼容结构
assert "overview" in result
assert "shots" in result
assert len(result["shots"]) >= 1
assert result["shots"][0]["shot_type_angle_movement"]
assert result["voiceover_script"]
# 系统提示确实被发送
assert patch_router.captured[0][0]["role"] == "system"
def test_fallback_when_xml_and_json_unparseable(self, job):
"""XML 与 JSON 均无法解析时回退到兜底脚本。"""
from packages.shared.ai_router import ai_router as _router
fake = _FakeClient(xml="not xml not json")
def _get(_key, variant=None):
return fake
orig = _router.get_llm_client
_router.get_llm_client = _get # type: ignore
job.image_analysis = {"images": []}
try:
from apps.worker.worker_app.tasks import viral_video as vv
result = vv._step_script_generation(job, {"images": []})
finally:
_router.get_llm_client = orig # type: ignore
assert isinstance(result, dict)
assert "voiceover_script" in result
assert "shots" in result
# ── 3) Review 使用 Reviewer + 自动重写 ─────────────────────────────
class TestReviewWiring:
def test_pass_path(self, job):
from apps.worker.worker_app.tasks import viral_video as vv
from packages.application.viral_video.reviewer import Reviewer, ReviewResult
copy_result = {
"title": "口红推荐",
"overview": {"theme": "口红推荐"},
"voiceover_script": "这款口红显白又持久",
"shots": [{"scene_and_dialogue": "展示口红"}],
}
job.intent_result = {"key_messages": ["显白", "持久"], "intent": "推广"}
pass_result = ReviewResult(passed=True, score=90, issues=[], rewrite_suggestions=[])
with patch.object(Reviewer, "review", return_value=pass_result):
out = vv._step_review(job, copy_result)
assert out["passed"] is True
def test_rewrite_path(self, job):
"""审核不通过时触发自动重写,并更新 job.copy_result。"""
from apps.worker.worker_app.tasks import viral_video as vv
from packages.application.viral_video.reviewer import Reviewer, ReviewResult
from packages.application.viral_video.schemas import FusionResult, ReviewIssue, ScriptSegment
copy_result = {
"title": "原标题",
"overview": {"theme": "原标题"},
"voiceover_script": "这款口红绝了",
"shots": [{"scene_and_dialogue": "展示"}],
}
job.intent_result = {"key_messages": ["显白"], "intent": "推广"}
fail_result = ReviewResult(
passed=False,
score=50,
issues=[ReviewIssue(dimension="违规词", severity="high", location="开头", text="绝了")],
rewrite_suggestions=["去掉夸大词"],
)
rewritten = FusionResult(
title="新标题",
hook="修改后钩子",
script_segments=[ScriptSegment(text="修改后口播正文")],
cta="行动号召",
word_count=10,
estimated_duration=10,
)
pass_after = ReviewResult(passed=True, score=88, issues=[], rewrite_suggestions=[])
with (
patch.object(Reviewer, "review", side_effect=[fail_result, pass_after]),
patch.object(Reviewer, "rewrite", return_value=rewritten),
):
out = vv._step_review(job, copy_result)
assert out["passed"] is True
# ── 4) 端到端:image 走 V2、script 走 storyboard loader ─────────────
class TestEndToEndLoaderUsed:
def test_image_v2_and_script_uses_storyboard(self, job):
from apps.worker.worker_app.tasks import viral_video as vv
from packages.application.viral_video import prompt_loader as pl
from packages.shared.ai_router import ai_router as _router
called_types: list[str] = []
real_get = pl.get_template
def spy_get(prompt_type, **kwargs):
called_types.append(prompt_type)
return real_get(prompt_type, **kwargs)
v2_image = {
"type": "product",
"name": "lipstick",
"brand": "品牌X",
"has_person": False,
"summary_markdown": "一支品牌X口红。",
}
fake = _FakeClient()
def _get(_key, variant=None):
return fake
orig = _router.get_llm_client
_router.get_llm_client = _get # type: ignore
job.image_analysis = {"images": []}
try:
with (
patch.object(pl, "get_template", side_effect=spy_get),
patch.object(vv, "_normalize_image_url", side_effect=lambda raw, idx: raw),
patch(
"worker_app.tasks.vision.analyze_images_v2",
return_value=[v2_image],
create=True,
),
):
img_step = vv._step_image_analysis(job)
img_res = img_step["images"][0]
copy_res = vv._step_script_generation(job, {"images": [img_res]})
finally:
_router.get_llm_client = orig # type: ignore
# V2 图片分析不经过 prompt_loader;脚本生成调用 storyboard 模板
assert "image_analysis" not in called_types
assert "storyboard" in called_types
assert copy_res["voiceover_script"]
# review 走 Reviewer.review
from packages.application.viral_video.reviewer import Reviewer, ReviewResult
pass_result = ReviewResult(passed=True, score=90, issues=[], rewrite_suggestions=[])
with patch.object(Reviewer, "review", return_value=pass_result) as mock_review:
review_res = vv._step_review(job, copy_res)
assert mock_review.called
assert isinstance(review_res, dict) and "passed" in review_res
+53
View File
@@ -430,3 +430,56 @@ class TestWSInitialSnapshot:
for p in patches:
p.stop()
assert any(m["type"] == "forwarder_reached" for m in received)
def test_image_analyzed_initial_snapshot_contains_image_analysis(self):
"""P0: image_analyzed 状态时初始快照必须带 image_analysis。"""
ia = {"images": [{"type": "product", "name": "X", "summary_markdown": "# X\nhello"}]}
job = _make_job(
status="image_analyzed",
user_id="user-a",
is_terminal=False,
image_analysis=ia,
copy_result=None,
generated_copy_text="",
storyboard=[],
)
received, _, _ = _run_ws_handshake(job=job)
assert received[0]["data"]["status"] == "image_analyzed"
assert received[0]["data"]["image_analysis"] == ia
def test_copy_generated_initial_snapshot_contains_copy_result(self):
"""P0: copy_generated 状态时初始快照必须带 copy_result/storyboard。"""
cr = {"shots": [{"time_range": "0-3s", "voiceover": "hi"}], "voiceover_script": "hi"}
sb = [{"order": 1, "text": "hi", "duration": 3.0}]
job = _make_job(
status="copy_generated",
user_id="user-a",
is_terminal=False,
image_analysis={"images": []},
copy_result=cr,
generated_copy_text="hi",
storyboard=sb,
)
received, _, _ = _run_ws_handshake(job=job)
data = received[0]["data"]
assert data["status"] == "copy_generated"
# _build_copy_result 会补 final_copy/suggested_copy/title 兜底
assert data["copy_result"]["shots"] == cr["shots"]
assert data["storyboard"] == sb
assert data["generated_copy_text"] == "hi"
assert data["image_analysis"] == {"images": []}
def test_initial_snapshot_without_business_fields_only_has_status(self):
"""running/pending 等中间态,无业务字段时不应塞空 dict/list。"""
job = _make_job(
status="running",
user_id="user-a",
is_terminal=False,
image_analysis=None,
copy_result=None,
generated_copy_text="",
storyboard=[],
)
received, _, _ = _run_ws_handshake(job=job)
data = received[0]["data"]
assert data == {"status": "running"}
+191
View File
@@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
"""vision v8 叙述优先 assembler / prompt 单元测试。
- assembler 输出仅 5 字段(type/name/brand/has_person/summary_markdown)
- images / 老 products 两种顶层键都能解析
- summary_markdown 正常时原样透传,不改写
- summary_markdown 缺失时才用一句话基础兜底
- _prompt:DB 有 active 模板原样使用,无记录回落到 prompts.py 默认 v8
"""
from __future__ import annotations
import sys
import types
from typing import Any
import pytest
from worker_app.tasks.vision import _prompt, assembler
# packages 层依赖 datetime.UTC(Python 3.11+)。开发机若为旧版本,prompt 相关用例
# 在 CI(3.11)上正常执行,本地直接跳过,避免污染基线。
_PY311 = sys.version_info >= (3, 11)
requires_packages = pytest.mark.skipif(not _PY311, reason="packages 需要 Python 3.11+")
REQUIRED_KEYS = {"type", "name", "brand", "has_person", "summary_markdown"}
# ---------- 正常 v8:叙述原样透传 ----------
def test_assemble_v8_store_passthrough() -> None:
md = "###店铺主体\n这是一家名为“御众堂”的线下门店内部,整体暖木色调……"
fj = {
"images": [
{
"type": "store",
"name": "御众堂门店",
"brand": "御众堂",
"has_person": False,
"summary_markdown": md,
}
]
}
r = assembler.assemble_result(0, fj, [])
assert REQUIRED_KEYS <= set(r.keys())
assert r["type"] == "store"
assert r["name"] == "御众堂门店"
assert r["brand"] == "御众堂"
assert r["has_person"] is False
assert r["summary_markdown"] == md
assert "_source" not in r
def test_assemble_v8_product() -> None:
md = "这是一瓶洗衣液,亮红色瓶身配白色按压泵头,瓶身正面印着品牌标识……"
fj = {
"images": [{"type": "product", "name": "洗衣液", "brand": "OMO", "has_person": False, "summary_markdown": md}]
}
r = assembler.assemble_result(0, fj, ["OMO"])
assert r["type"] == "product"
assert r["summary_markdown"] == md
def test_assemble_v8_person() -> None:
md = "画面里是一位年轻女性,穿白色T恤、黑色阔腿裤,神情自信……"
fj = {"images": [{"type": "person", "name": "年轻女性", "brand": "", "has_person": True, "summary_markdown": md}]}
r = assembler.assemble_result(0, fj, [])
assert r["type"] == "person"
assert r["has_person"] is True
assert r["summary_markdown"] == md
def test_assemble_v8_scene() -> None:
fj = {
"images": [
{"type": "scene", "name": "海边日落", "brand": "", "has_person": False, "summary_markdown": "海边……"}
]
}
r = assembler.assemble_result(0, fj, [])
assert r["type"] == "scene"
# ---------- 顶层 products 老键兼容(assembler 层)----------
def test_assemble_top_level_products_key() -> None:
fj = {"products": [{"type": "store", "name": "门店", "brand": "御众堂", "summary_markdown": "门店……"}]}
r = assembler.assemble_result(0, fj, [])
assert r["brand"] == "御众堂"
assert r["type"] == "store"
# ---------- 字段缺失的异常兜底 ----------
def test_assemble_missing_summary_uses_basic_fallback() -> None:
fj = {"images": [{"type": "store", "name": "御众堂门店", "brand": "御众堂", "has_person": False}]}
r = assembler.assemble_result(0, fj, [])
assert REQUIRED_KEYS <= set(r.keys())
assert r["summary_markdown"]
assert "御众堂" in r["summary_markdown"]
assert r.get("_source") == "summary_missing"
def test_assemble_invalid_type_defaults_scene() -> None:
fj = {"images": [{"type": "weird", "name": "x", "summary_markdown": ""}]}
r = assembler.assemble_result(0, fj, [])
assert r["type"] == "scene"
assert r["summary_markdown"] # basic fallback
def test_assemble_empty_fast_json_uses_ocr_hint() -> None:
r = assembler.assemble_result(0, {}, ["御众堂"])
assert REQUIRED_KEYS <= set(r.keys())
assert "御众堂" in r["name"]
assert r.get("_source") == "empty_fast_json"
def test_assemble_none_input() -> None:
r = assembler.assemble_result(0, None, [])
assert REQUIRED_KEYS <= set(r.keys())
assert r["type"] == "scene"
# ---------- 布尔归一化 ----------
def test_coerce_bool() -> None:
assert assembler._coerce_bool(True) is True
assert assembler._coerce_bool(1) is True
assert assembler._coerce_bool("true") is True
assert assembler._coerce_bool(False) is False
assert assembler._coerce_bool(0) is False
assert assembler._coerce_bool("否") is False
# ---------- _prompt 解析 ----------
@pytest.fixture(autouse=True)
def _clear_prompt_cache() -> Any:
_prompt.invalidate_cache()
yield
_prompt.invalidate_cache()
def _fake_tpl(system_prompt: str = "DB_V8_PROMPT_XYZ") -> Any:
return types.SimpleNamespace(
system_prompt=system_prompt,
user_prompt_template="地址:{image_url},OCR:{ocr_text}",
version=8,
)
@requires_packages
def test_resolve_uses_db_prompt(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(_prompt, "_load_db_template", lambda: _fake_tpl())
sys_prompt, user_prompt = _prompt.resolve_fast_prompt("http://img", "御众堂")
assert sys_prompt == "DB_V8_PROMPT_XYZ"
assert "http://img" in user_prompt
assert "御众堂" in user_prompt
@requires_packages
def test_resolve_pro_uses_db_prompt(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(_prompt, "_load_db_template", lambda: _fake_tpl("DB_PRO_PROMPT"))
sys_prompt, _ = _prompt.resolve_pro_prompt()
assert sys_prompt == "DB_PRO_PROMPT"
@requires_packages
def test_resolve_falls_back_to_default(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(_prompt, "_load_db_template", lambda: None)
default = _prompt._default_template()
sys_prompt, _ = _prompt.resolve_fast_prompt()
assert sys_prompt == default["system_prompt"]
@requires_packages
def test_resolve_caches(monkeypatch: pytest.MonkeyPatch) -> None:
calls = {"n": 0}
def _load() -> Any:
calls["n"] += 1
return _fake_tpl("CACHED")
monkeypatch.setattr(_prompt, "_load_db_template", _load)
s1, _ = _prompt.resolve_fast_prompt()
s2, _ = _prompt.resolve_fast_prompt()
assert s1 == s2 == "CACHED"
assert calls["n"] == 1

Some files were not shown because too many files have changed in this diff Show More