feat: 查重率百分比计算+跨项目查重 #1660 #1675
Reference in New Issue
Block a user
Delete Branch "feat/duplicate-rate-scope-1660"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
查重系统需要支持跨项目全局查重,以及更精细的查重率百分比计算。
改动
1. check_duplicate() 增加 scope 参数
scope="project"(默认):当前行为不变scope="user":按 user_id 跨项目查重duration_sec参数:时长 ±15% 预过滤,减少不必要比对2. check_batch_duplicate() 同步增加 scope 参数
3. compute_duplicate_rate() 公式升级
find_duplicate_segments()返回的重复片段计算float改为dict:{duplicate_rate, visual_similarity, match_count}4. check_duplicate_task() 改造
scope="user"跨项目查重 + 时长预过滤duplicate_rate、match_count、visual_similarity5. GeneratedVideo 模型 + Migration
match_count(Integer)、visual_similarity(Float) 字段6. Repository 层
list_by_user()方法,支持时长预过滤7. 调用方同步适配
dedup_helpers.py适配新 dict 返回值和 scope 参数单元测试
test_duplicate_rate_scope.py(6 个测试类覆盖 scope/duration/formula/return_dict/backward_compat)test_duplicate_rate.py(7 个测试适配 dict 返回)test_dedup_helpers_user_id.pymock 返回值技术约束
Closes #1660
- check_duplicate() 新增 scope/user_id/duration_sec 参数 scope='user' 跨项目全局查重,时长 ±15% 预过滤 - check_batch_duplicate() 同步新增 scope 参数 - compute_duplicate_rate() 重写为新公式: duplicate_rate = (frame_match_rate * 0.4 + temporal_coverage_rate * 0.6) * 100 返回 dict: {duplicate_rate, visual_similarity, match_count} - check_duplicate_task() 改用 scope='user' + 时长预过滤, 计算并写入 duplicate_rate/match_count/visual_similarity - dedup_helpers.py 同步适配新 dict 返回值和 scope 参数 - GeneratedVideo 新增 match_count/visual_similarity 字段 - Migration 064: generated_videos 表新增两列 - Repository: 新增 list_by_user() 方法 - 56 个相关单测全部通过🚀 预览环境已部署
【阻塞级判定】
📊 审查概览
🔴 阻塞级问题(必须修复)
[packages/adapters/sqlalchemy_impl/generated_video_repository.py: 98] 单位不匹配导致时长过滤失效
dedup.py中计算duration_sec时,使用了fingerprint.duration / 1000,这意味着传入list_by_user的是秒。而在list_by_user的实现中,直接将此值与数据库字段GeneratedVideoModel.duration进行比较。通常视频处理中数据库存储的duration为毫秒。如果数据库字段单位为毫秒,这里将导致逻辑错误(例如:视频时长 60秒 = 60000毫秒,查询条件duration >= 60会匹配所有时长大于 60ms 的视频,即几乎全部视频),导致时长预过滤失效。GeneratedVideoModel.duration的存储单位。如果数据库存的是毫秒,list_by_user的参数或内部过滤逻辑需要乘以 1000 转换为毫秒进行比较;或者确保调用方传入毫秒(但当前调用方明确传入了秒)。[packages/adapters/sqlalchemy_impl/generated_video_repository.py: 98] 缺失数据量限制导致严重性能隐患
compute_duplicate_rate中使用了.limit(200)仅查询最近的 200 个视频进行比对。重构后,新代码调用list_by_user(user_id)并在 Repository 层直接执行.all()。对于拥有大量视频(如数千个)的用户,这将一次性把所有视频加载到内存,并在后续的循环中进行逐帧指纹比对,极大概率导致 Worker 内存溢出(OOM)或任务超时。list_by_user方法中添加默认的limit参数(例如默认 200 或 500),或者在dedup.py调用时确保分页处理,避免全量数据加载和比对。💡 改进建议(不阻塞合并)
except Exception as rate_err块中,仅重置了generated_video.duplicate_rate = None,但没有重置新增的match_count和visual_similarity字段。虽然领域模型有默认值,但为了逻辑严谨性,建议在异常分支也显式处理这两个字段(例如设为 0 或 None),保持数据状态的一致性。✅ 良好实践
getattr并提供默认值来处理新旧模型字段的兼容,确保了数据迁移期间的平滑过渡。compute_duplicate_rate的返回值结构化(dict),比单一浮点数更能表达丰富的查重指标。server_default,避免了全表更新,提高了迁移效率。🤖 由 AI 代码审查机器人自动生成 | 2026-09-03 15:56:45 | 模型:
🗑️ 预览环境已清理
PR #1675 已关闭或合并,对应的预览环境已被清理。