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.
 

9.8 KiB

AI 对话生成业务流程总览

更新日期: 2026-02-13
版本: v2.0 (补齐业务表写入环节)


🎯 业务场景映射

目标类型(target_type)与存储关系

target_type 前端传值 业务场景 存储目标表 必传关联 ID 资源类型 (type)
1 storyboard 分镜生图 storyboard_images storyboard_id -
1 storyboard 分镜生视频 storyboard_videos storyboard_id -
2 character 角色生图 project_resources project_id + element_tag_id 1 (角色)
3 scene 场景生图 project_resources project_id + element_tag_id 2 (场景)
4 prop 道具生图 project_resources project_id + element_tag_id 3 (道具)

注意: 音效和配音不通过对话生成,使用其他 API 接口处理。


🔄 完整业务流程

步骤 1: 创建对话会话

API: POST /api/v1/ai/conversations

请求示例 (角色生图):

{
  "projectId": "019d1234-5678-7abc-def0-123456789abc",
  "targetType": 2,
  "targetId": "019d1234-5678-7abc-def0-character001",
  "tagId": "019d1234-5678-7abc-def0-tag-young",
  "mediaType": 1,
  "title": "张三-少年版 - 图片生成"
}

数据库记录:

INSERT INTO ai_conversations (
  conversation_id, user_id, project_id,
  target_type, target_id, tag_id, media_type,
  title, status
) VALUES (
  '019d1234-...', '019d1234-...', '019d1234-...',
  2, '019d1234-...', '019d1234-...', 1,
  '张三-少年版 - 图片生成', 1
);

步骤 2: 发送消息 + 触发生成

API: POST /api/v1/ai/conversations/{conversation_id}/messages

请求示例 A (仅发送消息):

{
  "content": "帮我生成一个日落场景"
}

请求示例 B (发送消息 + 自动触发生成):

{
  "content": "生成一个日落场景,色调偏暖",
  "generate": {
    "generationType": "image",
    "modelId": "dall-e-3",
    "aiParams": {
      "resolution": "1024",
      "aspectRatio": "1:1"
    }
  }
}

内部流程:

  1. 创建用户消息 (role=USER)
  2. 保存到 ai_conversation_messages
  3. 如果提供 generate 对象 → 调用 trigger_ai_generation()
  4. 创建 AI 任务 → ai_jobs 表 (status=PENDING)
  5. 投递 Celery 任务到队列

数据库记录:

-- 用户消息
INSERT INTO ai_conversation_messages (
  message_id, conversation_id, user_id, role, content,
  meta_data, order_index, ai_job_id
) VALUES (
  '019d1234-...', '019d1234-...', '019d1234-...', 1, '生成一个日落场景',
  '{"generate": {...}}', 0, '019d1234-job-001'
);

-- AI 任务
INSERT INTO ai_jobs (
  ai_job_id, user_id, project_id, job_type, status,
  input_data, model_name
) VALUES (
  '019d1234-job-001', '019d1234-...', '019d1234-...', 1, 1,
  '{"prompt": "生成一个日落场景", ...}', 'dall-e-3'
);

步骤 3: Celery 异步任务执行

任务: generate_image_task / generate_video_task

执行流程:

  1. 更新任务状态 → PROCESSING
  2. 调用 AI Provider (OpenAI, FLUX, Doubao, etc.)
  3. 下载生成的文件
  4. 上传到自有 OSS (MinIO)
  5. 更新任务状态 → COMPLETED

数据库更新:

UPDATE ai_jobs SET
  status = 3,  -- COMPLETED
  progress = 100,
  output_data = '{
    "file_url": "https://minio.example.com/ai-generated/images/019d1234.png",
    "file_size": 2048576,
    "width": 1024,
    "height": 1024,
    "checksum": "abc123...",
    "storage_provider": "minio",
    "storage_path": "/ai-generated/images/019d1234.png"
  }',
  completed_at = now()
WHERE ai_job_id = '019d1234-job-001';

步骤 4: 🆕 自动写入业务表

服务: AIGenerationResultService.save_generation_result()

执行逻辑:

  1. 通过 ai_job_id 查询关联的消息 (ai_conversation_messages)
  2. 获取对话上下文 (ai_conversations)
  3. 根据 target_type + media_type 路由到对应的保存方法

场景 A: 分镜图片 (target_type=1, media_type=1)

INSERT INTO storyboard_images (
  image_id, storyboard_id, name, url,
  status, is_active, version,
  width, height, file_size, format, checksum,
  storage_provider, storage_path,
  ai_model, ai_prompt, ai_params,
  created_at, completed_at
) VALUES (
  '019d1234-img-001', '019d1234-storyboard-001',
  'AI生成图片 - 20260213_143022', 'https://minio.../019d1234.png',
  2, true, 1,
  1024, 1024, 2048576, 'png', 'abc123...',
  'minio', '/ai-generated/images/019d1234.png',
  'dall-e-3', '生成一个日落场景', '{"resolution": "1024", ...}',
  now(), now()
);

场景 B: 角色/场景/道具 (target_type=2/3/4, media_type=1)

INSERT INTO project_resources (
  project_resource_id, project_id, name, type,
  file_url, file_size, mime_type, width, height, checksum,
  element_tag_id, ai_job_id, meta_data,
  created_by, created_at, updated_at
) VALUES (
  '019d1234-res-001', '019d1234-proj-001', 'AI生成角色 - 20260213',
  1,  -- ResourceType.CHARACTER
  'https://minio.../019d1234.png', 2048576, 'image/png', 1024, 1024, 'abc123...',
  '019d1234-tag-young', '019d1234-job-001',
  '{"conversation_id": "...", "prompt": "...", "ai_params": {...}}',
  '019d1234-user-001', now(), now()
);

📊 数据流示意图

┌─────────────────┐
│  前端创建会话    │
│  POST /conversations
└────────┬────────┘
         ↓
┌─────────────────┐
│ ai_conversations│ (记录 target_type, target_id, tag_id)
└────────┬────────┘
         ↓
┌─────────────────┐
│ 前端发送消息     │
│ POST /messages  │
│ (附带 generate) │
└────────┬────────┘
         ↓
┌───────────────────────┐
│ ai_conversation_messages│ (记录 content, ai_job_id)
└────────┬──────────────┘
         ↓
┌─────────────────┐
│  创建 AI 任务    │
└────────┬────────┘
         ↓
┌─────────────────┐
│   ai_jobs       │ (status=PENDING)
└────────┬────────┘
         ↓
┌─────────────────┐
│ Celery Worker   │
│ 调用 AI Provider│
│ 下载文件        │
│ 上传到 OSS      │
└────────┬────────┘
         ↓
┌─────────────────┐
│   ai_jobs       │ (status=COMPLETED, output_data)
└────────┬────────┘
         ↓
┌─────────────────────────┐
│ 🆕 自动写入业务表         │
│ AIGenerationResultService│
└────────┬────────────────┘
         ↓
  ┌──────┴──────┐
  │             │
  ↓             ↓
┌─────────────┐ ┌─────────────┐
│storyboard_  │ │project_     │
│images/videos│ │resources    │
└─────────────┘ └─────────────┘

🔑 关键字段说明

ai_conversations 表

  • target_type: 目标类型(1=分镜 2=角色 3=场景 4=道具 5=资源)
  • target_id: 目标对象 ID(storyboard_id / character_id / scene_id / prop_id)
  • tag_id: 标签 ID(用于区分变体,如"少年版"、"中年版")
  • media_type: 媒体类型(1=图片 2=视频)

ai_conversation_messages 表

  • role: 消息角色(1=USER 用户消息, 2=ASSISTANT AI回复)
  • content: 消息内容(用户提示词或 AI 回复)
  • ai_job_id: 关联的 AI 任务 ID(如果触发了生成)
  • meta_data: 扩展数据(包含 generate 配置、mentions、reference_images)

ai_jobs 表

  • job_type: 任务类型(1=图片 2=视频 3=音效 4=配音)
  • status: 任务状态(1=等待 2=处理中 3=已完成 4=失败)
  • output_data: 输出结果(file_url, file_size, width, height, checksum 等)

前端查询指南

查询角色生成的所有图片

SELECT * FROM project_resources
WHERE project_id = '019d1234-proj-001'
  AND type = 1  -- CHARACTER
  AND element_tag_id = '019d1234-tag-young'
  AND deleted_at IS NULL
ORDER BY created_at DESC;

查询分镜的所有图片

SELECT * FROM storyboard_images
WHERE storyboard_id = '019d1234-storyboard-001'
  AND is_active = true
ORDER BY version DESC, created_at DESC;

查询某个对话生成的资源

-- 1. 通过 conversation_id 查询所有消息
SELECT * FROM ai_conversation_messages
WHERE conversation_id = '019d1234-conv-001';

-- 2. 通过 ai_job_id 查询任务结果
SELECT * FROM ai_jobs
WHERE ai_job_id IN (
  SELECT ai_job_id FROM ai_conversation_messages
  WHERE conversation_id = '019d1234-conv-001'
);

-- 3. 通过 meta_data 查询资源(如果需要)
SELECT * FROM project_resources
WHERE meta_data->>'conversation_id' = '019d1234-conv-001';

🎉 完成标志

现在前端可以直接从业务表查询生成的资源,无需解析 ai_jobs.output_data

优势:

  1. 统一数据结构:所有资源都在业务表中
  2. 支持版本管理:通过 version 字段管理多版本
  3. 支持标签筛选:通过 element_tag_id 精准查询
  4. 支持状态管理:通过 is_active 控制激活状态

📝 相关文档