# 機能設計書 29-画像生成

## 概要

本ドキュメントは、Giselleシステムにおける「画像生成」機能の設計仕様を定義する。この機能は、AIモデル（OpenAI、Google、Fal）を使用して画像を生成するコア機能である。

### 本機能の処理概要

**業務上の目的・背景**：AIワークフローにおいて、テキストプロンプトから画像を生成する機能が必要である。この機能は、複数の画像生成AIプロバイダーに対応し、生成された画像をストレージに保存して後続のノードや出力で利用可能にする。

**機能の利用シーン**：
- ワークフロー内の画像生成ノードが実行される場合
- プロンプトからアートワークやイラストを生成する場合
- ドキュメントや記事用の挿絵を自動生成する場合
- マーケティング素材の画像を生成する場合

**主要な処理内容**：
1. 生成コンテキストから入力メッセージ（プロンプト）を構築する
2. 使用するプロバイダー（Fal、OpenAI、Google）を決定する
3. AI SDK経由で画像生成APIを呼び出す
4. 生成された画像のバイナリデータを取得する
5. 画像タイプを検出してファイル名を決定する
6. 画像をストレージに保存する
7. 生成結果（画像メタデータ）を保存する

**関連システム・外部連携**：
- AI Provider APIs: Fal.ai、OpenAI DALL-E/GPT-Image、Google Imagen
- Storage: 生成画像の永続化

**権限による制御**：
- 各プロバイダーのAPIキー認証

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | ワークフローエディタ画面 | 主画面 | 画像生成ノードの実行 |
| 18 | プレイグラウンド画面 | 主画面 | アプリ実行テストでの画像生成 |

## 機能種別

AI処理 / 画像生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| context | GiselleContext | Yes | Giselleコンテキスト | 有効なコンテキストオブジェクト |
| generation | QueuedGeneration | Yes | キュー済みの生成オブジェクト | status="queued"であること |
| signal | AbortSignal | No | 中断シグナル | - |

### 入力データソース

- Generation: 生成コンテキスト（operationNode、sourceNodes）
- Storage: 関連ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| images | Image[] | 生成された画像のメタデータ配列 |

### Image型の構造

| フィールド | 型 | 説明 |
|-----------|-----|------|
| id | ImageId | 画像の一意識別子 |
| contentType | string | MIMEタイプ（image/png等） |
| filename | string | ファイル名（{id}.{ext}） |
| pathname | string | アクセスパス |

### 出力先

- Storage: `generations/{generationId}/generated-images/{filename}`
- Storage: 生成オブジェクト（CompletedGeneration）

## 処理フロー

### 処理シーケンス

```
1. 生成実行準備（useGenerationExecutor）
   ├─ 生成ステータスをrunningに更新
   └─ ファイルリゾルバー等の初期化

2. メッセージ構築
   └─ buildMessageObjectでコンテキストノードからプロンプトを構築

3. プロバイダー分岐
   ├─ fal: generateImageWithFal
   ├─ openai: generateImageWithOpenAI
   └─ google: generateImageWithGoogle

4. 画像生成API呼び出し
   ├─ experimental_generateImage（Fal、OpenAI）
   └─ generateText（Google）

5. 画像処理
   ├─ detectImageTypeで画像タイプを検出
   ├─ ImageId.generate()でID生成
   ├─ setGeneratedImageでストレージに保存
   └─ Imageメタデータを構築

6. 完了処理
   └─ finishGenerationで結果保存
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[useGenerationExecutor]
    B --> C[buildMessageObject]
    C --> D{プロバイダー判定}
    D -->|fal| E[generateImageWithFal]
    D -->|openai| F[generateImageWithOpenAI]
    D -->|google| G[generateImageWithGoogle]
    E --> H[experimental_generateImage]
    F --> I[experimental_generateImage]
    G --> J[generateText]
    H --> K[画像結果取得]
    I --> K
    J --> K
    K --> L[detectImageType]
    L --> M{画像タイプ?}
    M -->|null| N[スキップ]
    M -->|valid| O[ImageId生成]
    O --> P[setGeneratedImage]
    P --> Q[Imageメタデータ構築]
    N --> R{次の画像?}
    Q --> R
    R -->|Yes| K
    R -->|No| S[finishGeneration]
    S --> T[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-29-01 | プロバイダー選択 | ノード設定のllm.providerに基づく | 常時 |
| BR-29-02 | 複数画像対応 | configurations.nで生成枚数を指定 | Fal、OpenAI使用時 |
| BR-29-03 | サイズ指定 | configurations.sizeで画像サイズを指定 | Fal、OpenAI使用時 |
| BR-29-04 | 画像タイプ検出 | マジックバイトで画像形式を判定 | 画像保存時 |
| BR-29-05 | 不明形式スキップ | 検出できない画像形式はスキップ | 画像処理時 |

### 計算ロジック

**画像タイプ検出**：
- PNG: 先頭バイトが`89 50 4E 47`
- JPEG: 先頭バイトが`FF D8 FF`
- WebP: 先頭が`52 49 46 46`かつオフセット8が`57 45 42 50`

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 画像保存 | Storage (generations/{id}/generated-images/) | INSERT | バイナリ画像保存 |
| 生成更新 | Storage (generations/) | UPDATE | 完了ステータスと結果保存 |

### テーブル別操作詳細

#### Storage: generations/{generationId}/generated-images/{filename}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | バイナリ | uint8Array | 画像バイナリデータ |

#### Storage: generations/{generationId}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | status | "completed"/"failed" | 完了時 |
| UPDATE | outputs | GenerationOutput（generated-image） | 完了時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| INVALID_PROVIDER | ValidationError | 不正なプロバイダー | 有効なプロバイダーを指定 |
| API_ERROR | ExternalError | 画像生成API呼び出し失敗 | リトライまたはプロバイダ確認 |
| ABORT_ERROR | CancelError | ResponseAbortedエラー | 正常終了として扱う |
| UNKNOWN_FORMAT | ValidationError | 画像形式が不明 | 生成パラメータを確認 |

### リトライ仕様

- API呼び出しエラー: 自動リトライなし
- 中断エラー: リトライなし（意図的な中断）

## トランザクション仕様

- 画像は個別にストレージに保存
- 全画像保存後に生成オブジェクトを更新
- 部分的な失敗はFailedGenerationとして記録

## パフォーマンス要件

- 画像生成: プロバイダーとサイズに依存（通常5〜30秒）
- 画像保存: 100ms以内
- 全体完了: 画像枚数 × 生成時間 + 保存時間

## セキュリティ考慮事項

- 各プロバイダーのAPIキー認証
- 生成画像はワークスペースに紐づくパスに保存
- アクセス権限チェックは呼び出し側で実施

## 備考

- Googleは画像生成にgenerateTextを使用（files配列で画像を返却）
- experimental_generateImageはAI SDKの実験的API
- detectImageTypeはユーティリティ関数で共通化

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

画像生成ノードと出力の構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | image-generation.ts | `packages/protocol/src/node/operations/image-generation.ts` | ImageGenerationNode型 |
| 1-2 | output.ts | `packages/protocol/src/generation/output.ts` | GenerationOutput（generated-image） |

**読解のコツ**: ImageGenerationNodeのcontentにはllm（provider、configurations）が含まれる。

#### Step 2: エントリーポイントを理解する

generateImage関数の全体構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | generate-image.ts | `packages/giselle/src/generations/generate-image.ts` | 関数シグネチャとプロバイダー分岐 |

**主要処理フロー**:
1. **32-36行目**: generateImage関数シグネチャ
2. **37-134行目**: useGenerationExecutor内の実行ロジック
3. **54-67行目**: buildMessageObjectでプロンプト構築
4. **70-108行目**: プロバイダー別分岐
5. **110-131行目**: エラーハンドリングとFailedGeneration

#### Step 3: プロバイダー別実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | generate-image.ts | `packages/giselle/src/generations/generate-image.ts` | generateImageWithFal（137-217行目） |
| 3-2 | generate-image.ts | `packages/giselle/src/generations/generate-image.ts` | generateImageWithOpenAI（219-300行目） |
| 3-3 | generate-image.ts | `packages/giselle/src/generations/generate-image.ts` | generateImageWithGoogle（302-368行目） |

#### Step 4: 画像保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utils.ts | `packages/giselle/src/generations/utils.ts` | setGeneratedImage、detectImageType関数 |

### プログラム呼び出し階層図

```
generateImage (generate-image.ts)
    │
    └─ useGenerationExecutor
           │
           ├─ buildMessageObject
           │
           ├─ プロバイダー分岐
           │      │
           │      ├─ generateImageWithFal
           │      │      └─ fal.image → generateImageAiSdk
           │      │
           │      ├─ generateImageWithOpenAI
           │      │      └─ openai.image → generateImageAiSdk
           │      │
           │      └─ generateImageWithGoogle
           │             └─ google → generateText → files[]
           │
           ├─ 各画像処理
           │      │
           │      ├─ detectImageType
           │      │
           │      ├─ ImageId.generate
           │      │
           │      └─ setGeneratedImage
           │             └─ storage.setBlob
           │
           └─ finishGeneration
                  └─ GenerationOutput (generated-image)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

generation ─────────────▶ buildMessageObject
                              │
                              ▼
                         prompt（テキスト）
                              │
                              ▼
                         プロバイダーAPI ───────▶ 画像バイナリ
                              │
                              ├─▶ detectImageType
                              │
                              ├─▶ ImageId生成
                              │
                              └─▶ setGeneratedImage
                                    │
                                    ▼
                              generated-images/{filename}
                                    │
                                    ▼
                              Image[] ─────────────────────▶ outputs
                                    │
                                    ▼
                              CompletedGeneration ─────────▶ Storage
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| generate-image.ts | `packages/giselle/src/generations/generate-image.ts` | ソース | メイン実装 |
| use-generation-executor.ts | `packages/giselle/src/generations/internal/use-generation-executor.ts` | ソース | 実行ユーティリティ |
| utils.ts | `packages/giselle/src/generations/utils.ts` | ソース | setGeneratedImage、detectImageType |
| image-generation.ts | `packages/protocol/src/node/operations/image-generation.ts` | ソース | ImageGenerationNode型 |
| output.ts | `packages/protocol/src/generation/output.ts` | ソース | GenerationOutput型 |
| giselle.ts | `packages/giselle/src/giselle.ts` | ソース | Giselleクラス（メソッド公開） |
