You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10 KiB
10 KiB
AI Service 快速开始指南
状态:数据库层已就绪 ✅
日期:2026-01-29
概述
AI Service 的数据库层已完全实现并可立即使用。本指南帮助您快速开始使用 AI Service。
当前状态
✅ 已完成
- 数据库表结构(4 张表)
- Models 定义(符合 Jointo 技术栈规范)
- 数据库迁移脚本
- 索引和约束
- 触发器和函数
⚠️ 待完成
- Credit Service 集成
- AI Providers 实现
- Celery Tasks 实现
- 单元测试和集成测试
数据库表
1. ai_models(AI 模型配置)
存储可用的 AI 模型及其定价信息。
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 生成任务的状态和结果。
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 调用的详细使用情况。
from app.models.ai_usage_log import AIUsageLog
4. ai_quotas(配额管理)
管理用户的 AI 使用配额和限流。
from app.models.ai_quota import AIQuota, QuotaPeriod
QuotaPeriod.DAILY # 1 - 每日配额
QuotaPeriod.MONTHLY # 2 - 每月配额
QuotaPeriod.TOTAL # 3 - 总配额
使用示例
1. 创建 AI 模型配置
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 任务
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. 更新任务状态
# 标记为处理中
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. 查询任务
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. 创建用户配额
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. 记录使用日志
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 操作:
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 层集成):
# 生成图片
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
数据库操作
查看表结构
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_*"
查看触发器
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "
SELECT tgname, tgrelid::regclass
FROM pg_trigger
WHERE tgname LIKE 'update_ai%';
"
手动重置配额
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "
SELECT reset_expired_quotas();
"
查询统计
# 任务统计
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;
"
下一步
立即可做
- ✅ 使用 Repository 进行 CRUD 操作
- ✅ 创建测试数据
- ✅ 查询和统计分析
- ✅ 编写数据迁移脚本
需要完成
- ⚠️ Credit Service 集成(积分预扣、确认、退还)
- ⚠️ AI Providers 实现(OpenAI, Stability, Runway 等)
- ⚠️ Celery Tasks 实现(异步任务处理)
- ⚠️ 单元测试和集成测试
注意事项
应用层引用完整性
所有关联字段都没有物理外键,必须在 Service 层验证:
# ❌ 错误:直接创建任务,不验证关联
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:
from datetime import datetime, timezone
# ✅ 正确
job.started_at = datetime.now(timezone.utc)
# ❌ 错误
job.started_at = datetime.now() # 缺少时区信息
枚举值使用
使用 IntEnum 而非字符串:
# ✅ 正确
job.job_type = AIJobType.IMAGE # 存储为 1
job.status = AIJobStatus.PENDING # 存储为 1
# ❌ 错误
job.job_type = "image" # 类型错误
job.status = "pending" # 类型错误
相关文档
支持
如有问题,请参考:
- 设计文档中的详细说明
- Changelog 中的变更记录
- 数据库表注释
- 代码中的类型提示和文档字符串