# AI Service 快速开始指南 > **状态**:数据库层已就绪 ✅ > **日期**:2026-01-29 ## 概述 AI Service 的数据库层已完全实现并可立即使用。本指南帮助您快速开始使用 AI Service。 ## 当前状态 ### ✅ 已完成 - 数据库表结构(4 张表) - Models 定义(符合 Jointo 技术栈规范) - 数据库迁移脚本 - 索引和约束 - 触发器和函数 ### ⚠️ 待完成 - Credit Service 集成 - AI Providers 实现 - Celery Tasks 实现 - 单元测试和集成测试 ## 数据库表 ### 1. ai_models(AI 模型配置) 存储可用的 AI 模型及其定价信息。 ```python from app.models.ai_model import AIModel, AIModelType, AIProvider, UnitType # 枚举值 AIModelType.TEXT # 1 - 文本模型 AIModelType.IMAGE # 2 - 图片模型 AIModelType.VIDEO # 3 - 视频模型 AIModelType.AUDIO # 4 - 音频模型 AIProvider.OPENAI # 1 AIProvider.ANTHROPIC # 2 AIProvider.GOOGLE # 3 AIProvider.STABILITY # 4 AIProvider.RUNWAY # 5 AIProvider.PIKA # 6 AIProvider.ELEVENLABS # 7 AIProvider.AZURE # 8 AIProvider.BAIDU # 9 AIProvider.ALIYUN # 10 AIProvider.CUSTOM # 99 UnitType.TOKEN # 1 - Token(文本模型) UnitType.IMAGE # 2 - 图片(图片模型) UnitType.SECOND # 3 - 秒(视频/音频模型) UnitType.REQUEST # 4 - 请求(通用计费单位) ``` ### 2. ai_jobs(AI 任务) 存储所有 AI 生成任务的状态和结果。 ```python from app.models.ai_job import AIJob, AIJobType, AIJobStatus # 任务类型 AIJobType.IMAGE # 1 - 图片生成 AIJobType.VIDEO # 2 - 视频生成 AIJobType.SOUND # 3 - 音效生成 AIJobType.VOICE # 4 - 配音生成 AIJobType.SUBTITLE # 5 - 字幕生成 AIJobType.TEXT_PROCESSING # 6 - 文本处理 AIJobType.RESOURCE # 7 - 资源生成 AIJobType.STORYBOARD_SCRIPT # 8 - 分镜脚本生成 AIJobType.SCRIPT_GENERATION # 9 - 剧本生成 # 任务状态 AIJobStatus.PENDING # 1 - 等待处理 AIJobStatus.PROCESSING # 2 - 处理中 AIJobStatus.COMPLETED # 3 - 已完成 AIJobStatus.FAILED # 4 - 失败 AIJobStatus.CANCELLED # 5 - 已取消 ``` ### 3. ai_usage_logs(使用日志) 记录每次 AI 调用的详细使用情况。 ```python from app.models.ai_usage_log import AIUsageLog ``` ### 4. ai_quotas(配额管理) 管理用户的 AI 使用配额和限流。 ```python from app.models.ai_quota import AIQuota, QuotaPeriod QuotaPeriod.DAILY # 1 - 每日配额 QuotaPeriod.MONTHLY # 2 - 每月配额 QuotaPeriod.TOTAL # 3 - 总配额 ``` ## 使用示例 ### 1. 创建 AI 模型配置 ```python from app.models.ai_model import AIModel, AIModelType, AIProvider, UnitType from app.utils.id_generator import generate_uuid from datetime import datetime, timezone # 创建 GPT-4 模型配置 gpt4_model = AIModel( model_id=generate_uuid(), model_name="gpt-4", display_name="GPT-4", description="OpenAI 最强大的语言模型", provider=AIProvider.OPENAI, model_type=AIModelType.TEXT, cost_per_unit=0.03, unit_type=UnitType.TOKEN, credits_per_unit=1, config={ "max_tokens": 8000, "temperature": 0.7 }, is_active=True, is_beta=False ) # 保存到数据库 db.add(gpt4_model) await db.commit() ``` ### 2. 创建 AI 任务 ```python from app.models.ai_job import AIJob, AIJobType, AIJobStatus from app.utils.id_generator import generate_uuid # 创建图片生成任务 job = AIJob( ai_job_id=generate_uuid(), user_id=user_id, job_type=AIJobType.IMAGE, status=AIJobStatus.PENDING, model_id=model_id, model_name="stable-diffusion", input_data={ "prompt": "一只可爱的猫咪在花园里玩耍", "width": 1024, "height": 1024, "style": "realistic" }, credits_used=10 ) db.add(job) await db.commit() ``` ### 3. 更新任务状态 ```python # 标记为处理中 job.status = AIJobStatus.PROCESSING job.started_at = datetime.now(timezone.utc) job.progress = 50 await db.commit() # 标记为完成 job.status = AIJobStatus.COMPLETED job.completed_at = datetime.now(timezone.utc) job.progress = 100 job.output_data = { "image_url": "https://storage.jointo.ai/images/123.png", "thumbnail_url": "https://storage.jointo.ai/images/123_thumb.png" } await db.commit() ``` ### 4. 查询任务 ```python from sqlalchemy import select # 查询用户的所有任务 result = await db.execute( select(AIJob) .where(AIJob.user_id == user_id) .order_by(AIJob.created_at.desc()) ) jobs = result.scalars().all() # 查询待处理的任务 result = await db.execute( select(AIJob) .where(AIJob.status == AIJobStatus.PENDING) .order_by(AIJob.created_at.asc()) .limit(10) ) pending_jobs = result.scalars().all() ``` ### 5. 创建用户配额 ```python from app.models.ai_quota import AIQuota, QuotaPeriod from datetime import datetime, timezone, timedelta # 创建每日图片生成配额 quota = AIQuota( quota_id=generate_uuid(), user_id=user_id, quota_type="image_generation", period=QuotaPeriod.DAILY, total_quota=50, used_quota=0, reset_at=datetime.now(timezone.utc) + timedelta(days=1) ) db.add(quota) await db.commit() ``` ### 6. 记录使用日志 ```python from app.models.ai_usage_log import AIUsageLog log = AIUsageLog( usage_log_id=generate_uuid(), user_id=user_id, ai_job_id=job.ai_job_id, model_id=model_id, units_used=1000, # 使用了 1000 tokens unit_type=UnitType.TOKEN, cost=0.03, credits_used=10, extra_metadata={ "prompt_tokens": 100, "completion_tokens": 900 } ) db.add(log) await db.commit() ``` ## Repository 使用 现有的 Repository 已经提供了基础的 CRUD 操作: ```python from app.repositories.ai_job_repository import AIJobRepository from app.repositories.ai_model_repository import AIModelRepository # 使用 Repository job_repo = AIJobRepository(db) model_repo = AIModelRepository(db) # 创建任务 job = await job_repo.create({ 'job_type': AIJobType.IMAGE, 'status': AIJobStatus.PENDING, 'user_id': user_id, 'input_data': {...} }) # 获取任务 job = await job_repo.get_by_id(job_id) # 更新任务 job = await job_repo.update(job_id, { 'status': AIJobStatus.COMPLETED, 'output_data': {...} }) # 获取用户任务列表 jobs = await job_repo.get_user_jobs( user_id=user_id, job_type=AIJobType.IMAGE, status=AIJobStatus.COMPLETED, limit=20 ) ``` ## API 使用 现有的 API 端点已经可以使用(需要完成 Service 层集成): ```bash # 生成图片 POST /api/v1/ai/generate-image { "prompt": "一只可爱的猫咪", "width": 1024, "height": 1024, "style": "realistic" } # 查询任务状态 GET /api/v1/ai/jobs/{job_id} # 取消任务 POST /api/v1/ai/jobs/{job_id}/cancel # 获取使用统计 GET /api/v1/ai/usage/stats?startDate=2026-01-01&endDate=2026-01-31 # 获取可用模型 GET /api/v1/ai/models?type=2 # 2 = IMAGE ``` ## 数据库操作 ### 查看表结构 ```bash docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d ai_jobs" ``` ### 查看索引 ```bash docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\di ai_*" ``` ### 查看触发器 ```bash docker exec jointo-server-postgres psql -U jointoAI -d jointo -c " SELECT tgname, tgrelid::regclass FROM pg_trigger WHERE tgname LIKE 'update_ai%'; " ``` ### 手动重置配额 ```bash docker exec jointo-server-postgres psql -U jointoAI -d jointo -c " SELECT reset_expired_quotas(); " ``` ### 查询统计 ```bash # 任务统计 docker exec jointo-server-postgres psql -U jointoAI -d jointo -c " SELECT job_type, status, COUNT(*) as count FROM ai_jobs GROUP BY job_type, status ORDER BY job_type, status; " # 模型统计 docker exec jointo-server-postgres psql -U jointoAI -d jointo -c " SELECT provider, model_type, COUNT(*) as count, SUM(CASE WHEN is_active THEN 1 ELSE 0 END) as active_count FROM ai_models GROUP BY provider, model_type; " ``` ## 下一步 ### 立即可做 1. ✅ 使用 Repository 进行 CRUD 操作 2. ✅ 创建测试数据 3. ✅ 查询和统计分析 4. ✅ 编写数据迁移脚本 ### 需要完成 1. ⚠️ Credit Service 集成(积分预扣、确认、退还) 2. ⚠️ AI Providers 实现(OpenAI, Stability, Runway 等) 3. ⚠️ Celery Tasks 实现(异步任务处理) 4. ⚠️ 单元测试和集成测试 ## 注意事项 ### 应用层引用完整性 所有关联字段都没有物理外键,必须在 Service 层验证: ```python # ❌ 错误:直接创建任务,不验证关联 job = AIJob(user_id=user_id, model_id=model_id, ...) # ✅ 正确:先验证关联是否存在 from app.repositories.user_repository import UserRepository from app.repositories.ai_model_repository import AIModelRepository user_repo = UserRepository(db) model_repo = AIModelRepository(db) if not await user_repo.exists(user_id): raise ValidationError("用户不存在") if not await model_repo.exists(model_id): raise ValidationError("模型不存在") job = AIJob(user_id=user_id, model_id=model_id, ...) ``` ### 时间戳使用 所有时间戳字段使用 TIMESTAMPTZ: ```python from datetime import datetime, timezone # ✅ 正确 job.started_at = datetime.now(timezone.utc) # ❌ 错误 job.started_at = datetime.now() # 缺少时区信息 ``` ### 枚举值使用 使用 IntEnum 而非字符串: ```python # ✅ 正确 job.job_type = AIJobType.IMAGE # 存储为 1 job.status = AIJobStatus.PENDING # 存储为 1 # ❌ 错误 job.job_type = "image" # 类型错误 job.status = "pending" # 类型错误 ``` ## 相关文档 - [AI Service 设计文档](../../requirements/backend/04-services/ai/ai-service.md) - [Changelog](../changelogs/2026-01-29-ai-service-complete-implementation.md) - [Jointo Tech Stack](../../../.claude/skills/jointo-tech-stack/SKILL.md) ## 支持 如有问题,请参考: 1. 设计文档中的详细说明 2. Changelog 中的变更记录 3. 数据库表注释 4. 代码中的类型提示和文档字符串