# 機能設計書 118-スクリプト操作（Script Operations）

## 概要

本ドキュメントは、TensorFlowにおけるPython関数をTensorFlowグラフ内で呼び出すpy_function機能の設計を記述する。

### 本機能の処理概要

Python関数をTensorFlowの計算グラフ内で実行する操作（PyFunc、EagerPyFunc）を提供する。TensorFlowのグラフ実行中にPythonの任意のコードを呼び出せるブリッジ機能であり、TensorFlowのOp集合では表現できない複雑な前処理やカスタムロジックの実装に利用される。

**業務上の目的・背景**：TensorFlowのOp体系では表現が困難な処理（外部ライブラリの呼び出し、複雑なデータ前処理、デバッグ用の印刷処理など）を、計算グラフ内にシームレスに組み込む必要がある。py_functionはこのギャップを埋める重要なブリッジ機能である。

**機能の利用シーン**：tf.dataパイプラインでのカスタムデータ前処理、NumPy/SciPy等の外部ライブラリ関数の呼び出し、デバッグ用のPrint出力、グラフモードでのカスタムロジック実装などで利用される。

**主要な処理内容**：
1. `PyFunc` - ステートフルなPython関数呼び出し（グラフモード）
2. `PyFuncStateless` - ステートレスなPython関数呼び出し（グラフモード）
3. `EagerPyFunc` - Eager実行モードでのPython関数呼び出し（非同期対応）

**関連システム・外部連携**：Python インタプリタ、NumPy等の外部ライブラリ、tf.dataパイプラインと連携する。

**権限による制御**：特になし。ただし、PyFuncはPythonインタプリタのGIL（Global Interpreter Lock）に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本機能はバックエンドAPI機能 |

## 機能種別

ブリッジ操作 / スクリプト実行

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | list of Tensor（Tin型） | Yes | Python関数への入力テンソル | >= 0個 |
| token | string | Yes | Python関数を識別するトークン | ランタイムに登録済みであること |
| Tin | list(type) | Yes | 入力テンソルの型リスト | >= 0個 |
| Tout | list(type) | Yes | 出力テンソルの型リスト | >= 0個 |
| is_async | bool | No（デフォルト: false） | 非同期実行フラグ（EagerPyFuncのみ） | - |

### 入力データソース

Python API呼び出し（tf.py_function, tf.numpy_function）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| output | list of Tensor（Tout型） | Python関数の戻り値をテンソルに変換したもの |

### 出力先

呼び出し元への戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. Python関数の登録
   └─ Python関数にユニークなトークンを割り当て
   └─ ランタイムの関数レジストリに登録

2. Op実行
   └─ TensorFlowランタイムからPyFunc/EagerPyFunc Opを実行
   └─ トークンに基づきPython関数を検索
   └─ 入力テンソルをNumPy配列に変換
   └─ Python関数を呼び出し
   └─ 戻り値をテンソルに変換

3. 結果返却
   └─ 変換されたテンソルをTensorFlowグラフに返却
```

### フローチャート

```mermaid
flowchart TD
    A[TFグラフ実行] --> B[PyFunc Op]
    B --> C[トークンで関数検索]
    C --> D[テンソル→NumPy変換]
    D --> E[Python関数呼び出し]
    E --> F[戻り値→テンソル変換]
    F --> G[TFグラフに返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-118-01 | ステートフル性 | PyFuncとEagerPyFuncはSetIsStatefulで登録され、最適化でのリオーダーが抑制される | PyFunc/EagerPyFunc使用時 |
| BR-118-02 | ステートレス性 | PyFuncStatelessはステートレスで、最適化によるリオーダーが許可される | PyFuncStateless使用時 |
| BR-118-03 | 非同期実行 | EagerPyFuncのis_async=trueで非同期Python関数を呼び出し可能 | EagerPyFunc使用時 |
| BR-118-04 | 形状推論不可 | 全PyFunc系Opの出力形状はUnknownShape（動的） | 全Op |

### 計算ロジック

Python関数の実行時間はユーザ定義関数に完全に依存する。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Internal | Python例外 | Python関数内で例外が発生 | Python関数のデバッグ |
| InvalidArgument | 型不一致 | 戻り値の型がToutと一致しない | 正しい型を返却するよう修正 |
| NotFound | トークン無効 | 登録されていないトークンの使用 | 関数登録を確認 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

PythonのGIL（Global Interpreter Lock）によりマルチスレッド実行が制限される。GPU実行中のPyFunc呼び出しはHost-Device間のデータ転送を伴うためボトルネックとなりやすい。

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

任意のPythonコードを実行するため、信頼できないコードの実行には注意が必要。

## 備考

- PyFuncはTF1.xのグラフモード向け。TF2.xではtf.py_function（EagerPyFunc）の使用が推奨される。
- 分散実行環境でのPyFuncの使用は、全ワーカーで同一のPython関数が利用可能である必要がある。
- tf.numpy_functionはPyFuncStatelessのラッパーで、入力をNumPy配列として渡す。

---

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

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

### 推奨読解順序

#### Step 1: Op定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | script_ops.cc | `tensorflow/core/ops/script_ops.cc` | 3つのPyFunc系Opの定義 |

**主要処理フロー**:
1. **21-28行目**: `PyFunc` Op - ステートフルなPython関数呼び出し。token属性で関数を識別。SetIsStatefulで副作用ありとマーク
2. **30-36行目**: `PyFuncStateless` Op - ステートレス版。SetIsStatefulが呼ばれていないため、オプティマイザによるリオーダーが可能
3. **38-46行目**: `EagerPyFunc` Op - Eager実行モード対応版。is_async属性で非同期実行をサポート。SetIsStatefulでマーク

**読解のコツ**: 3つのOpは基本的に同じ入出力構造（input: Tin, output: Tout, token: string）を持つ。違いはステートフル性とis_async属性の有無。全てのOpがUnknownShapeを返すため、形状推論は行われない。

#### Step 2: カーネル実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | py_func.py | `tensorflow/python/lib/core/py_func.py`（推定） | Python側の関数レジストリとブリッジ実装 |

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

```
Python API (tf.py_function / tf.numpy_function)
    │
    ├─ Python関数レジストリに登録
    │      └─ token生成
    │
    └─ EagerPyFunc / PyFunc Op
           │
           ├─ Input: テンソル列(Tin)
           ├─ token → Python関数検索
           ├─ テンソル → NumPy変換
           ├─ Python関数呼び出し
           ├─ 戻り値 → テンソル変換
           └─ Output: テンソル列(Tout)
```

### データフロー図

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

TF Tensor(Tin) ──▶ NumPy変換 ──▶ Python関数 ──▶ テンソル変換 ──▶ TF Tensor(Tout)
                                      │
                              token で関数解決
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| script_ops.cc | `tensorflow/core/ops/script_ops.cc` | ソース | PyFunc/EagerPyFunc Op定義 |
| common_shape_fns.h | `tensorflow/core/framework/common_shape_fns.h` | ヘッダー | UnknownShape形状推論関数 |
| op.h | `tensorflow/core/framework/op.h` | ヘッダー | REGISTER_OPマクロ定義 |
