BRAIN MARKET · UX MOCK · 2026-07-19
AIサムネイル生成機能 — 体験フローモック
実現方式はバックグラウンド生成 + 10秒間隔ポーリングです。生成には最大2分程度かかるため、SSEで接続を張り続けるのではなく、リクエストを即時受理して著者は執筆を続けながら完成を待つ体験にします。API仕様は esa #356「AIサムネイル生成機能 API設計書」に準拠しています。
記事編集画面(/a/[id]/edit)での体験
実際の編集画面に UI を組み込んだ状態です。基本タブは「成功Ver / 失敗Ver」の2つ。成功Ver選択中は右側に派生フロー「離脱(生成中に他ページへ遷移) / 設定済み(再生成) / 上限(レート制限)」のボタンが表示されます。「▶ フローを自動再生」を押すか、チップで各ステップに移動してください。
Brain
カテゴリ▼
キーワードで検索
下書き保存
…
プレビュー
販売設定に進む
1
目次
目次はありません
著者の任意操作
FOR BACKEND
想定シーケンス(非同期・esa #356 準拠)
エンドポイントは既存 eyecatch/collaboration と同じ単数形 member ルート(POST/GET/PATCH /v2/articles/:id/ai_thumbnail)。生成は Sidekiq ジョブが OpenAI を直接呼んで完結します(SNS/SQS は不使用)。
%%{init: {"theme": "neutral", "themeVariables": {"sequenceNumberColor": "#ffffff"}}}%%
sequenceDiagram
autonumber
actor U as 著者
participant FE as front (Nuxt 3)
participant API as api (Rails)
participant W as Sidekiq ジョブ
participant AI as OpenAI
rect rgb(253, 244, 237)
Note over U,AI: ① 受付 — POST は即時応答。モーダルは閉じて執筆継続
U->>FE: 「3案を生成する」
FE->>API: POST /v2/articles/:id/ai_thumbnail
Note right of API: 上限超過は 429 / processing 中は既存を 200 で返す
API->>W: レコード作成(pending) + ジョブ enqueue
API-->>FE: { status: "pending" }
end
rect rgb(244, 247, 252)
Note over U,AI: ② バックグラウンド生成(1〜2分) — 生成とポーリングが並行
par Sidekiq ジョブ
W->>AI: 画像プロンプト生成(gpt-5.4-nano)
AI-->>W: prompt(レコードに保存)
W->>AI: images.generate(gpt-image-2 / n:3 ※1リクエスト)
AI-->>W: 画像×3
W->>W: 3候補を保存 → completed / failed
W->>W: ベル通知を作成 ※BE追加要件
and フロントのポーリング
loop 10秒間隔(仮5分で打ち切り)
FE->>API: GET /v2/articles/:id/ai_thumbnail
API-->>FE: { status, candidates?, error_message? }
end
end
end
rect rgb(240, 249, 243)
Note over U,API: ③ 完了後 — 編集ページはスナックバー / 他ページはベル通知
alt completed
U->>FE: 候補から1枚選択
FE->>API: PATCH { candidate_index }
API-->>FE: アイキャッチ確定(EyecatchSerializer 同形)
else failed
FE-->>U: エラーカード + 「もう一度生成する」(全体再生成)
end
end
ステータスAPI レスポンス(設計書より)
GET /v2/articles/:id/ai_thumbnail // 生成中 { "status": "processing" } // 完了 { "status": "completed", "candidates": [ { "candidate_index": 0, "image_url": "https://.../0.png" }, { "candidate_index": 1, "image_url": "https://.../1.png" }, { "candidate_index": 2, "image_url": "https://.../2.png" } ] } // 失敗(全体failed のみ。候補単位の失敗はない) { "status": "failed", "error_message": "画像生成に失敗しました" } // POST が上限超過のとき 429 Too Many Requests { "code": "ai_thumbnail_rate_limit_exceeded_error", "message": "1日あたりの生成上限に達しました。時間を空けてお試しください" }