# 機能設計書 77-埋め込み生成

## 概要

本ドキュメントは、GiselleワークフローシステムのRAG（Retrieval-Augmented Generation）パイプラインにおける埋め込み生成機能の設計を記述する。この機能は、テキストをベクトル埋め込みに変換する。

### 本機能の処理概要

**業務上の目的・背景**：RAGシステムにおいて、テキストの意味的類似性を計算するためには、テキストを数値ベクトル（埋め込み）に変換する必要がある。この機能は、OpenAI、Google、Cohereなどの埋め込みモデルを使用して、テキストを高次元ベクトルに変換する。変換されたベクトルは、ベクトルストアに保存され、類似検索に使用される。

**機能の利用シーン**：
- ドキュメントチャンクをベクトルストアに保存する際の埋め込み生成
- 検索クエリを埋め込みに変換して類似検索を実行する際
- RAGパイプラインのインジェスト処理の一部として

**主要な処理内容**：
1. 設定されたAPIキーとプロファイルで埋め込みモデルを初期化
2. 単一テキストまたは複数テキストの埋め込みを生成
3. 使用量メトリクスの収集とコールバック通知
4. エラー発生時の適切なエラーハンドリング

**関連システム・外部連携**：
- Vercel AI SDKを介したembedding API呼び出し
- OpenAI、Google、Cohereの埋め込みAPI

**権限による制御**：埋め込みプロバイダのAPIキーへのアクセスが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | ドキュメントVector Store設定画面 | 補助機能 | テキストのベクトル埋め込み変換処理 |

## 機能種別

AI/ML処理・外部API連携

## 入力仕様

### 入力パラメータ（createAiSdkEmbedder関数）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| config.apiKey | string | Yes | 埋め込みプロバイダのAPIキー | 空文字でないこと |
| config.profile | EmbeddingProfile | Yes | 埋め込みプロファイル（モデル、プロバイダ、次元数） | - |
| config.maxRetries | number | No | 最大リトライ回数（デフォルト: 3） | - |
| config.embeddingComplete | EmbeddingCompleteCallback | No | 埋め込み完了時のコールバック | - |
| config.transport | "gateway" \| "provider" | No | 通信経路（デフォルト: "provider"） | - |
| config.headers | Record<string, string> | No | 追加HTTPヘッダー | - |
| getModel | (modelName: string) => EmbeddingModel | Yes | モデル取得関数 | - |

### 入力パラメータ（embed/embedMany関数）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text / texts | string / string[] | Yes | 埋め込み対象のテキスト | - |
| options.headers | Record<string, string> | No | リクエスト固有のHTTPヘッダー | - |

### 入力データソース

- インジェストパイプラインからのチャンクテキスト
- クエリサービスからの検索クエリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| embedding | number[] | 単一テキストの埋め込みベクトル |
| embeddings | number[][] | 複数テキストの埋め込みベクトル配列 |

### 出力先

- 呼び出し元（インジェストパイプライン、クエリサービス）への戻り値
- embeddingCompleteコールバックへのメトリクス通知

## 処理フロー

### 処理シーケンス

```
1. 設定バリデーション
   └─ APIキーが空でないことを確認

2. プロファイル情報の抽出
   └─ model、provider、dimensionsを取得

3. モデルインスタンスの取得
   └─ getModel(modelName)でEmbeddingModelを取得

4. 埋め込み生成（embed/embedMany）
   ├─ 開始時刻を記録
   ├─ AI SDKのembed/embedMany関数を呼び出し
   │     └─ maxRetriesによるリトライ機能付き
   └─ 終了時刻を記録

5. コールバック通知（embeddingComplete設定時）
   ├─ 使用量メトリクスの正規化
   └─ コールバック関数の呼び出し

6. 結果返却
   └─ embedding / embeddings を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{APIキー検証}
    B -->|空| C[ConfigurationError throw]
    B -->|有効| D[プロファイル情報抽出]
    D --> E[EmbedderFunction返却]

    subgraph embed_call [embed/embedMany呼び出し]
        F[開始時刻記録] --> G[getModel呼び出し]
        G --> H[AI SDK embed/embedMany]
        H --> I{成功?}
        I -->|No| J[EmbeddingError throw]
        I -->|Yes| K[終了時刻記録]
        K --> L{コールバック設定?}
        L -->|Yes| M[使用量正規化]
        M --> N[コールバック呼び出し]
        L -->|No| O[結果返却]
        N --> O
    end

    E --> embed_call
    C --> P[終了]
    J --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | APIキー必須 | APIキーが空の場合はConfigurationErrorをスロー | 常時 |
| BR-02 | デフォルトリトライ | maxRetriesのデフォルト値は3回 | maxRetries未指定時 |
| BR-03 | デフォルト通信経路 | transportのデフォルト値は"provider" | transport未指定時 |
| BR-04 | コールバックエラー無視 | embeddingCompleteコールバックでのエラーはログのみで処理続行 | コールバック実行時 |
| BR-05 | 使用量正規化 | usage情報のtokens、imageTokensを正規化して返却 | コールバック実行時 |

### 計算ロジック

使用量正規化：
```typescript
const normalizeUsage = (rawUsage: unknown): { tokens: number; imageTokens?: number } | undefined => {
    if (!rawUsage || typeof rawUsage !== "object") return undefined;
    const tokens = typeof usageWithNumbers.tokens === "number" ? usageWithNumbers.tokens : 0;
    const normalized = { tokens };
    if (typeof usageWithNumbers.imageTokens === "number") {
        normalized.imageTokens = usageWithNumbers.imageTokens;
    }
    return normalized;
};
```

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

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

本機能はデータベースを直接操作しない。外部埋め込みAPIへのHTTPリクエストを行う。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConfigurationError.missingField | APIキーが空または未設定 | 有効なAPIキーを設定 |
| - | EmbeddingError.apiError | 埋め込みAPI呼び出しエラー | APIキー、ネットワーク、レート制限を確認 |

### リトライ仕様

- デフォルトで3回のリトライを実行
- リトライ回数はconfig.maxRetriesで設定可能
- AI SDKの内部リトライメカニズムを使用

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

該当なし（外部API呼び出しのみ）

## パフォーマンス要件

- 単一テキストの埋め込み生成は通常1秒以内
- embedManyは複数テキストを効率的にバッチ処理
- ネットワークレイテンシとAPIレート制限に依存

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

- APIキーは環境変数または暗号化されたシークレットから取得
- AI Gatewayを使用する場合はgatewayトランスポートを選択可能
- 入力テキストは外部APIに送信されるため、機密データの取り扱いに注意

## 備考

- 対応プロバイダ: OpenAI、Google、Cohere
- 埋め込み次元数はプロファイルで定義（例: 1536、3072）
- providerMetadataでプロバイダ固有のメタデータを取得可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/rag/src/embedder/types.ts` | EmbedderFunction、EmbeddingMetrics型定義 |

**読解のコツ**: EmbedderFunctionがembed、embedMany、embeddingCompleteの3つのメンバを持つオブジェクト型であることを理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ai-sdk-embedder.ts | `packages/rag/src/embedder/ai-sdk-embedder.ts` | createAiSdkEmbedder関数 |

**主要処理フロー**:
1. **19-26行目**: createAiSdkEmbedder関数の定義とAPIキーバリデーション
2. **27-28行目**: プロファイルからモデル情報抽出
3. **30-51行目**: normalizeUsageヘルパー関数
4. **54-92行目**: embed関数の実装
5. **94-136行目**: embedMany関数の実装
6. **137行目**: embeddingCompleteの設定

#### Step 3: AI SDK連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ai-sdk-embedder.ts | `packages/rag/src/embedder/ai-sdk-embedder.ts` | AI SDK呼び出し部分 |

**主要処理フロー**:
- **57-62行目**: embed関数でAI SDKのembed呼び出し
- **100-105行目**: embedMany関数でAI SDKのembedMany呼び出し
- **maxRetries**: リトライ設定をAI SDKに渡す

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

```
createAiSdkEmbedder(config, getModel)
    │
    └─ 返却: EmbedderFunction
           │
           ├─ embed(text, options?)
           │      │
           │      ├─ getModel(modelName)
           │      │      └─ EmbeddingModel取得
           │      │
           │      ├─ AI SDK embed()
           │      │      └─ { embedding, usage, providerMetadata }
           │      │
           │      ├─ normalizeUsage(usage)
           │      │      └─ { tokens, imageTokens? }
           │      │
           │      └─ embeddingComplete?(metrics)
           │             └─ コールバック通知
           │
           └─ embedMany(texts, options?)
                  │
                  ├─ getModel(modelName)
                  │
                  ├─ AI SDK embedMany()
                  │      └─ { embeddings, usage, providerMetadata }
                  │
                  ├─ normalizeUsage(usage)
                  │
                  └─ embeddingComplete?(metrics)
```

### データフロー図

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

config ─────────▶ createAiSdkEmbedder() ─────▶ EmbedderFunction
   │                       │
   ├─ apiKey               ├─ バリデーション
   ├─ profile              ├─ プロファイル抽出
   └─ options              └─ 関数構築

text/texts ─────▶ embed()/embedMany() ─────▶ embedding(s)
   │                       │                      │
   │                       ├─ getModel()          │
   │                       ├─ AI SDK呼び出し      │
   │                       └─ メトリクス収集       │
   │                              │               │
   │                              ▼               │
   │                       embeddingComplete() ───┼───▶ EmbeddingMetrics
   │                              │               │
   │                              └─ コールバック   │
   │                                              │
   └──────────────────────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ai-sdk-embedder.ts | `packages/rag/src/embedder/ai-sdk-embedder.ts` | ソース | メイン実装 |
| types.ts | `packages/rag/src/embedder/types.ts` | ソース | 型定義 |
| profiles.ts | `packages/rag/src/embedder/profiles.ts` | ソース | プロファイル別初期化 |
| errors.ts | `packages/rag/src/errors.ts` | ソース | エラークラス定義 |
| index.ts | `packages/rag/src/embedder/index.ts` | ソース | エクスポート |
