# 機能設計書 76-チャンク分割

## 概要

本ドキュメントは、GiselleワークフローシステムのRAG（Retrieval-Augmented Generation）パイプラインにおけるチャンク分割機能の設計を記述する。この機能は、ドキュメントテキストを検索用の小さなチャンクに分割する。

### 本機能の処理概要

**業務上の目的・背景**：RAGシステムにおいて、大きなドキュメントをそのままベクトル埋め込みすることは非効率であり、検索精度も低下する。この機能は、ドキュメントを適切なサイズのチャンクに分割することで、効率的な埋め込み生成と高精度な類似検索を実現する。行ベースの分割アルゴリズムにより、コードやドキュメントの論理的な構造を維持しながら分割を行う。

**機能の利用シーン**：
- GitHubリポジトリのコードをベクトルストアに取り込む際の前処理
- ドキュメントファイルをベクトルストアに登録する際の前処理
- Webページの内容をRAG用に処理する際の前処理

**主要な処理内容**：
1. テキストを改行で行に分割
2. 設定された最大行数（maxLines）でチャンクを構成
3. オーバーラップ（overlap）により前後チャンク間の文脈を維持
4. 最大文字数（maxChars）を超える場合は段階的に縮小
5. 単一行でもmaxCharsを超える場合は文字単位で分割

**関連システム・外部連携**：RAGパイプライン（インジェスト処理）の一部として使用される。

**権限による制御**：本機能は内部処理関数であり、権限による制御は行わない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | ドキュメントVector Store設定画面 | 補助機能 | ドキュメントの検索用チャンク分割処理 |

## 機能種別

テキスト処理・データ変換

## 入力仕様

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

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| maxLines | number | Yes | 1チャンクあたりの最大行数 | 1以上 |
| overlap | number | Yes | チャンク間のオーバーラップ行数 | 0以上かつmaxLines未満 |
| maxChars | number | Yes | 1チャンクあたりの最大文字数 | 1以上 |

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

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | 分割対象のテキスト | - |

### 入力データソース

- インジェストパイプラインからのドキュメントコンテンツ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| chunks | string[] | 分割されたチャンクの配列 |

### 出力先

- インジェストパイプラインへの戻り値（埋め込み生成処理に渡される）

## 処理フロー

### 処理シーケンス

```
1. 設定値のバリデーション
   └─ maxLines >= 1、overlap >= 0、overlap < maxLines、maxChars >= 1

2. テキストを行に分割
   └─ text.split("\n")

3. チャンク生成ループ
   ├─ 初期チャンク情報の作成（createInitialChunk）
   │     └─ オーバーラップを考慮した開始位置から最大行数分を取得
   │
   ├─ 縮小ループ（content.length > maxChars の間）
   │     ├─ 縮小モード判定（getShrinkMode）
   │     │     ├─ OVERLAP_REDUCTION: オーバーラップ削減
   │     │     ├─ LINE_REDUCTION: 行数削減
   │     │     └─ CHARACTER_SPLIT: 文字分割
   │     │
   │     └─ モードに応じた縮小処理
   │           ├─ reduceOverlapGradually: オーバーラップを半分に削減
   │           ├─ reduceLineCountGradually: 行数を1減らす
   │           └─ splitLongContent: 文字単位で分割
   │
   └─ 次チャンクの開始位置計算（nextStartIndex）

4. 空チャンクのフィルタリング
   └─ chunks.filter((chunk) => chunk.length > 0)

5. チャンク配列の返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{設定値バリデーション}
    B -->|NG| C[Error throw]
    B -->|OK| D[テキストを行に分割]
    D --> E{全行処理完了?}
    E -->|Yes| F[空チャンクフィルタ]
    F --> G[チャンク配列返却]
    E -->|No| H[初期チャンク作成]
    H --> I{content > maxChars?}
    I -->|No| J[チャンク追加]
    I -->|Yes| K{縮小モード判定}
    K -->|OVERLAP_REDUCTION| L[オーバーラップ削減]
    K -->|LINE_REDUCTION| M[行数削減]
    K -->|CHARACTER_SPLIT| N[文字分割]
    L --> I
    M --> I
    N --> O[分割チャンク追加]
    J --> P[次開始位置計算]
    O --> P
    P --> E
    G --> Q[終了]
    C --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 最初のチャンクはオーバーラップなし | 最初のチャンクは前のチャンクが存在しないためオーバーラップ0 | 最初のチャンク生成時 |
| BR-02 | 段階的縮小 | maxCharsを超える場合、オーバーラップ→行数→文字の順で縮小 | maxChars超過時 |
| BR-03 | オーバーラップ半減 | オーバーラップ削減は半分ずつ減らす（Math.floor(overlap / 2)） | オーバーラップ削減時 |
| BR-04 | 文字分割後はオーバーラップスキップ | 文字分割を行った場合、次チャンクのオーバーラップはスキップ | 文字分割実行時 |
| BR-05 | 空チャンク除外 | 長さ0のチャンクは結果から除外 | 常時 |

### 計算ロジック

縮小モード判定（ShrinkMode）：
```typescript
if (currentOverlap > 0) return OVERLAP_REDUCTION;
if (currentLineCount > 1) return LINE_REDUCTION;
return CHARACTER_SPLIT;
```

次チャンク開始位置計算：
```typescript
const nextStart = endIndex - overlapAmount;
return Math.max(nextStart, startIndex + 1);  // 最低1行は進む
```

文字分割：
```typescript
Array.from({ length: Math.ceil(content.length / maxChars) }, (_, k) =>
    content.slice(k * maxChars, (k + 1) * maxChars)
)
```

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

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

本機能はデータベースを直接操作しない。純粋な文字列処理関数である。

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | maxLines must be at least 1 | maxLines < 1 | 1以上の値を指定 |
| - | overlap cannot be negative | overlap < 0 | 0以上の値を指定 |
| - | overlap must be less than maxLines | overlap >= maxLines | maxLines未満の値を指定 |
| - | maxChars must be at least 1 | maxChars < 1 | 1以上の値を指定 |

### リトライ仕様

本機能は同期的な純粋関数であり、リトライの概念は適用されない。

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

該当なし（データベース操作なし）

## パフォーマンス要件

- 大きなテキストでもメモリ効率的に処理すること
- 10MBのテキストを1秒以内に処理すること（推定）

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

- 入力テキストに対する特別なサニタイズは行わない
- 出力チャンクは入力テキストの部分文字列のみ（変換なし）

## 備考

- 本実装は行ベースの分割（Line Chunker）であり、セマンティックな分割ではない
- コードファイルの分割に適しており、関数やクラスの境界を考慮した分割ではない
- 将来的により高度なチャンカー（セマンティックチャンカー等）の追加が検討される可能性あり

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: ChunkerFunctionは単純な `(text: string) => string[]` という関数型であり、入出力が明確。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | line-chunker.ts | `packages/rag/src/chunker/line-chunker.ts` | createLineChunker関数 |

**主要処理フロー**:
1. **28-44行目**: createLineChunker関数の定義とバリデーション
2. **49-51行目**: テキストを行に分割し、結果配列を初期化
3. **56-60行目**: チャンクのオーバーラップ判定
4. **62行目**: 初期チャンク作成
5. **66-91行目**: 縮小ループ（maxChars制約を満たすまで）
6. **95-100行目**: チャンク追加と次開始位置計算
7. **103行目**: 空チャンクフィルタリング

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | line-chunker.ts | `packages/rag/src/chunker/line-chunker.ts` | ヘルパー関数群（107-209行目） |

**主要処理フロー**:
- **107-116行目**: getShrinkMode - 縮小モード判定
- **118-123行目**: shouldUseOverlap - オーバーラップ適用判定
- **125-139行目**: nextStartIndex - 次チャンク開始位置計算
- **141-157行目**: buildChunk - ChunkInfo構築
- **159-167行目**: createInitialChunk - 初期チャンク作成
- **169-184行目**: reduceOverlapGradually - オーバーラップ削減
- **186-203行目**: reduceLineCountGradually - 行数削減
- **205-209行目**: splitLongContent - 文字分割

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

```
createLineChunker(options)
    │
    └─ chunk(text)  [返却される関数]
           │
           ├─ text.split("\n")
           │
           ├─ [ループ] while (i < lines.length)
           │     │
           │     ├─ shouldUseOverlap()
           │     │
           │     ├─ createInitialChunk()
           │     │      └─ buildChunk()
           │     │
           │     ├─ [縮小ループ] while (content > maxChars)
           │     │      │
           │     │      ├─ getShrinkMode()
           │     │      │
           │     │      ├─ reduceOverlapGradually()
           │     │      │      └─ buildChunk()
           │     │      │
           │     │      ├─ reduceLineCountGradually()
           │     │      │      └─ buildChunk()
           │     │      │
           │     │      └─ splitLongContent()
           │     │
           │     └─ nextStartIndex()
           │
           └─ chunks.filter()
```

### データフロー図

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

テキスト ────────▶ split("\n") ────────────▶ 行配列
                                                 │
                                                 ▼
                            createInitialChunk() ────▶ ChunkInfo
                                                 │
                            ┌────────────────────┴─────────────────┐
                            │                                      │
                       [maxChars以下]                         [maxChars超過]
                            │                                      │
                            ▼                                      ▼
                     チャンク追加                           縮小処理
                            │                              (overlap→lines→chars)
                            │                                      │
                            │                            ┌─────────┴──────────┐
                            │                            │                    │
                            │                     [文字分割以外]          [文字分割]
                            │                            │                    │
                            │                            ▼                    ▼
                            │                     ChunkInfo更新          複数チャンク追加
                            │                            │                    │
                            └────────────────────────────┴────────────────────┘
                                                 │
                                                 ▼
                                          nextStartIndex()
                                                 │
                                                 ▼
                                          filter(空除去)
                                                 │
                                                 ▼
                                            string[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| line-chunker.ts | `packages/rag/src/chunker/line-chunker.ts` | ソース | メイン実装 |
| types.ts | `packages/rag/src/chunker/types.ts` | ソース | ChunkerFunction型定義 |
| index.ts | `packages/rag/src/chunker/index.ts` | ソース | エクスポート |
| line-chunker.test.ts | `packages/rag/src/chunker/line-chunker.test.ts` | テスト | ユニットテスト |
