# AI Service 完整实现 > **日期**:2026-01-29 > **类型**:Feature > **影响范围**:AI Service, Database, Models, Repositories ## 概述 完成 AI Service 的数据库层实现,包括 Models 修复、数据库迁移脚本创建和执行。 ## 变更内容 ### 1. Models 修复 #### 1.1 ai_job.py - ✅ 使用 TIMESTAMPTZ 替代 datetime - ✅ 使用 JSONB 替代 JSON - ✅ 使用 SMALLINT 存储枚举值 - ✅ 添加完整的字段注释 - ✅ 添加表级约束和索引 - ✅ 添加 CheckConstraint 验证进度范围 #### 1.2 ai_model.py - ✅ 修复 unique 和 sa_column 冲突 - ✅ 使用 TIMESTAMPTZ 替代 datetime - ✅ 使用 JSONB 替代 JSON - ✅ 使用 SMALLINT 存储枚举值 - ✅ 添加完整的字段注释 - ✅ 添加 GIN 索引支持 JSONB 查询 #### 1.3 ai_quota.py - ✅ 使用 TIMESTAMPTZ 替代 datetime - ✅ 使用 SMALLINT 存储枚举值 - ✅ 添加 UniqueConstraint - ✅ 添加 CheckConstraint 验证配额范围 - ✅ 添加完整的字段注释 #### 1.4 ai_usage_log.py - ✅ 重命名 `metadata` 为 `extra_metadata`(避免 SQLModel 保留字冲突) - ✅ 使用 TIMESTAMPTZ 替代 datetime - ✅ 使用 JSONB 替代 JSON - ✅ 使用 SMALLINT 存储枚举值 - ✅ 添加 CheckConstraint 验证单位类型 - ✅ 添加完整的字段注释 ### 2. 数据库迁移 #### 2.1 创建迁移脚本 - ✅ 文件:`server/alembic/versions/20260129_1800_create_ai_service_tables.py` - ✅ 创建 4 张表:ai_models, ai_jobs, ai_usage_logs, ai_quotas - ✅ 无外键约束,应用层保证引用完整性 - ✅ 所有关联字段添加索引 - ✅ JSONB 字段添加 GIN 索引 - ✅ 添加 updated_at 触发器 - ✅ 创建配额重置函数 `reset_expired_quotas()` #### 2.2 执行迁移 ```bash docker exec jointo-server-app alembic upgrade head ``` **结果**: - ✅ 迁移版本:20260129_1800 - ✅ 所有表创建成功 - ✅ 所有索引创建成功 - ✅ 所有触发器创建成功 - ✅ 所有注释添加成功 ### 3. 技术规范遵循 #### 3.1 数据库设计规范 - ✅ 使用 TIMESTAMPTZ 存储所有时间戳(ADR 006) - ✅ 使用 SMALLINT 存储枚举值 - ✅ 使用 JSONB 存储 JSON 数据 - ✅ 无物理外键约束,应用层保证引用完整性 - ✅ 所有关联字段添加索引 - ✅ 所有字段添加中文注释 #### 3.2 命名规范 - ✅ 表名:snake_case - ✅ 字段名:snake_case - ✅ 索引名:idx_{table}_{column} - ✅ 约束名:{table}_{constraint_type} #### 3.3 性能优化 - ✅ JSONB 字段使用 GIN 索引 - ✅ 复合索引支持常见查询 - ✅ 部分索引减少索引大小 - ✅ WHERE 条件索引提升查询效率 ## 数据库表结构 ### ai_models(AI 模型配置表) - 主键:model_id (UUID) - 唯一约束:model_name - 索引:provider, model_type, is_active, config (GIN) - 触发器:update_updated_at ### ai_jobs(AI 任务表) - 主键:ai_job_id (UUID) - 索引:user_id, project_id, storyboard_id, consumption_log_id, job_type, status, model_id, created_at, input_data (GIN), output_data (GIN) - 约束:progress CHECK (0-100) - 触发器:update_updated_at ### ai_usage_logs(AI 使用日志表) - 主键:usage_log_id (UUID) - 索引:user_id, ai_job_id, model_id, created_at, extra_metadata (GIN) - 约束:unit_type CHECK (1-4) ### ai_quotas(AI 配额表) - 主键:quota_id (UUID) - 唯一约束:(user_id, quota_type, period) - 索引:user_id, quota_type, reset_at - 约束:period CHECK (1-3), used_quota CHECK (0-total_quota) - 触发器:update_updated_at ## 待完成工作 ### 高优先级 1. **Credit Service 集成** - [ ] 在 AIService 中注入 CreditService - [ ] 实现积分预扣逻辑 - [ ] 实现积分确认逻辑 - [ ] 实现积分退还逻辑 - [ ] 添加事务保证 2. **AI Providers 实现** - [ ] 完善 OpenAI Provider(图片、文本、配音、字幕) - [ ] 实现错误处理和重试逻辑 - [ ] 添加速率限制 3. **Celery Tasks 实现** - [ ] 实现 generate_image_task - [ ] 实现 generate_video_task - [ ] 实现 generate_sound_task - [ ] 实现 generate_voice_task - [ ] 实现 generate_subtitle_task - [ ] 实现 process_text_task - [ ] 添加任务状态更新 - [ ] 添加错误处理 ### 中优先级 4. **Repository 完善** - [ ] 添加应用层引用完整性验证 - [ ] 实现 exists() 方法 - [ ] 添加事务支持 5. **测试** - [ ] 编写单元测试 - [ ] 编写集成测试 - [ ] 测试覆盖率 > 80% ### 低优先级 6. **文档** - [ ] API 文档完善 - [ ] 使用示例 - [ ] 故障排查指南 ## 测试验证 ### 数据库验证 ```bash # 检查迁移版本 docker exec jointo-server-app alembic current # 输出:20260129_1800 (head) # 检查表结构 docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d ai_jobs" # 输出:完整的表结构,包含所有字段、索引、约束、触发器 # 检查索引 docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\di ai_*" # 输出:所有 AI 相关索引 # 检查触发器 docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "SELECT tgname FROM pg_trigger WHERE tgname LIKE 'update_ai%';" # 输出:update_ai_models_updated_at, update_ai_jobs_updated_at, update_ai_quotas_updated_at ``` ### Models 验证 ```bash # 导入测试 docker exec jointo-server-app python -c "from app.models import AIJob, AIModel, AIQuota, AIUsageLog; print('✅ Models 导入成功')" ``` ## 影响范围 ### 新增文件 - `server/alembic/versions/20260129_1800_create_ai_service_tables.py` - `docs/server/changelogs/2026-01-29-ai-service-complete-implementation.md` ### 修改文件 - `server/app/models/ai_job.py` - `server/app/models/ai_model.py` - `server/app/models/ai_quota.py` - `server/app/models/ai_usage_log.py` ### 数据库变更 - 新增表:ai_models, ai_jobs, ai_usage_logs, ai_quotas - 新增索引:12+ 个索引 - 新增触发器:3 个 updated_at 触发器 - 新增函数:reset_expired_quotas() ## 回滚方案 如需回滚: ```bash # 回滚到上一个版本 docker exec jointo-server-app alembic downgrade -1 # 或回滚到指定版本 docker exec jointo-server-app alembic downgrade 20260129_1700 ``` ## 注意事项 1. **应用层引用完整性**:所有关联字段都没有物理外键,必须在 Service 层验证 2. **metadata 字段冲突**:SQLModel 保留 `metadata` 字段,使用 `extra_metadata` 替代 3. **unique 和 sa_column**:不能同时使用,unique 应在 Column 中定义 4. **TIMESTAMPTZ**:所有时间戳字段必须使用 TIMESTAMP(timezone=True) 5. **枚举值**:使用 SMALLINT 存储,Python 层使用 IntEnum ## 相关文档 - [AI Service 设计文档](../../requirements/backend/04-services/ai/ai-service.md) - [数据库设计规范](../../requirements/database-design.md) - [ADR 006: TIMESTAMPTZ for Event Timestamps](../../architecture/adrs/006-timestamptz-for-event-timestamps.md) - [Jointo Tech Stack](../../../.claude/skills/jointo-tech-stack/SKILL.md) ## 作者 - Kiro AI Assistant - 日期:2026-01-29