feat(worker): #1970 AI 标签 backfill 支持 force 重打降级记录 #1989

Merged
auto-approve-bot merged 1 commits from feat/1970-force-backfill-downgraded-tags into develop 2026-09-19 10:49:21 +08:00
Owner

背景

#1987 修复 Celery 任务注册、DOUBAO_VISION_MODEL 配置正确后,此前视觉 API 失败写入的降级记录 {"inherited_tags": [...]}(非 NULL)不会被 backfill 捞起(find_untagged 只匹配 ai_tags IS NULL),tag 任务本身也按幂等跳过,存量降级片段永远无法补全真实 AI 标签(含 has_text)。

改动

  • find_untagged(limit, include_downgraded=False):force 模式下用 ai_tags['has_text'].as_string() IS NULL(→ JSON/JSONB ->>'has_text')同时匹配 NULL 记录和缺 has_text 键的降级记录;has_text=true/false 的完整记录始终排除。
  • tag_atom_clip_task(atom_clip_id, force=False):force=True 时放行缺 has_text 的降级记录并覆盖写入;完整标签始终跳过保持幂等。
  • backfill_atom_clip_tags(..., force=False):透传 kwargs={"force": ...} 给 tag 任务。

用法

Celery 调用(管理员/运维):

backfill_atom_clip_tags.delay(force=True)  # 含降级记录全量重打
backfill_atom_clip_tags.delay(max_clips=20, force=True)  # 小批验证

验证

  • 新增 7 个回归测试(仓储过滤 SQL 在 SQLite 验证跨库语义;任务层直接调用原函数,兼容 tests/unit 旧测试向 sys.modules 注入 celery_app MagicMock 不还原的污染)
  • 全量 tests/unit:15828 passed / 28 skipped;ruff/black/isort 通过

兼容性

force 默认 False,默认行为完全不变(仅 ai_tags IS NULL)。

## 背景 #1987 修复 Celery 任务注册、DOUBAO_VISION_MODEL 配置正确后,此前视觉 API 失败写入的降级记录 `{"inherited_tags": [...]}`(非 NULL)不会被 backfill 捞起(`find_untagged` 只匹配 `ai_tags IS NULL`),tag 任务本身也按幂等跳过,存量降级片段永远无法补全真实 AI 标签(含 has_text)。 ## 改动 - `find_untagged(limit, include_downgraded=False)`:force 模式下用 `ai_tags['has_text'].as_string() IS NULL`(→ JSON/JSONB `->>'has_text'`)同时匹配 NULL 记录和缺 has_text 键的降级记录;`has_text=true/false` 的完整记录始终排除。 - `tag_atom_clip_task(atom_clip_id, force=False)`:force=True 时放行缺 has_text 的降级记录并覆盖写入;完整标签始终跳过保持幂等。 - `backfill_atom_clip_tags(..., force=False)`:透传 `kwargs={"force": ...}` 给 tag 任务。 ## 用法 Celery 调用(管理员/运维): ```python backfill_atom_clip_tags.delay(force=True) # 含降级记录全量重打 backfill_atom_clip_tags.delay(max_clips=20, force=True) # 小批验证 ``` ## 验证 - 新增 7 个回归测试(仓储过滤 SQL 在 SQLite 验证跨库语义;任务层直接调用原函数,兼容 tests/unit 旧测试向 sys.modules 注入 celery_app MagicMock 不还原的污染) - 全量 tests/unit:**15828 passed / 28 skipped**;ruff/black/isort 通过 ## 兼容性 force 默认 False,默认行为完全不变(仅 ai_tags IS NULL)。
xiaoxia added 1 commit 2026-09-19 10:43:54 +08:00
feat(worker): #1970 AI 标签 backfill 支持 force 重打降级记录
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 / 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 / Build Staging Worker 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 42s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m0s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m39s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m43s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m9s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 2m15s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m30s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 4m49s
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) 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
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m31s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 26s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 26s
AI Code Review / AI Code Review (pull_request) Successful in 6m33s
9558969a31
DOUBAO_VISION_MODEL 修复后,此前视觉 API 失败写入的
{'inherited_tags': [...]} 降级记录(非 NULL)不会被默认 backfill 捞起,
tag 任务也按幂等跳过。

- find_untagged 加 include_downgraded:用 ai_tags['has_text'].as_string()
  IS NULL 同时匹配 NULL 与缺 has_text 键的降级记录(json/jsonb 通用,
  has_text=true/false 的完整记录排除)
- tag_atom_clip_task / backfill_atom_clip_tags 加 force 参数,
  backfill 透传 kwargs={'force': ...}
- 7 个回归测试(任务层测试兼容旧测试 sys.modules 注入 MagicMock 的污染)

🚀 预览环境已部署

项目 详情
PR号 #1989
预览链接 https://pr-1989.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1989 | | 预览链接 | [https://pr-1989.preview.xiaoxiajianji.com](https://pr-1989.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot merged commit a1f25a4426 into develop 2026-09-19 10:49:21 +08:00
auto-approve-bot deleted branch feat/1970-force-backfill-downgraded-tags 2026-09-19 10:49:24 +08:00

🗑️ 预览环境已清理

PR #1989 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1989 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.