> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/workflows/ja/gaido/developer-guide/execution-engine-changelog.md).

# Execution Engine更新履歴

Workflows Execution Engineのバージョンごとの変更点。

このページでは、Execution Engine の歴史的な変更と移行例を保持しています。新しい変更については、 [Workflows パッケージの変更履歴](https://github.com/roboflow/inference/blob/main/workflows/CHANGELOG.md).

{% hint style="info" %}
エンジンの動作変更は、現在パッケージの変更履歴の「Execution engine」サブセクションに記録されます。パッケージのリリースでは、同梱されるエンジンのバージョンが記録され、パッケージ `0.2.2`から始まります。エンジンのバージョンはパッケージのバージョンとは別のままで、引き続きワークフローとブロックの互換性を制御します。
{% endhint %}

***

## Execution Engine `v1.16.0` | inference `1.5.2`

**何が変わったか**

* VLM が切り抜き画像内でオブジェクトを見つけられない場合、 `PARENT` 座標を使用するワークフロー出力は、元の画像サイズを報告するようになりました。 `OWN` 座標を使用する出力は、引き続き切り抜きサイズを報告します。

***

## Execution Engine `v1.15.1` | inference `1.5.1`

**何が変わったか**

* ローカルのワークフローモデルの読み込み中に発生したモデルアクセス失敗では、HTTP 402、403、423 のステータスが保持され、汎用の HTTP 500 エラーとして表示されなくなりました。
* **ステップのワーカースレッドは、呼び出し元の完全な `contextvars` コンテキストを** 並列で実行されるステップ（ `run_in_parallel`経由で生成されたネストされたブロックのワーカープールを含む）は、送信スレッドのコンテキストのタスクごとのスナップショット内で実行されます。以前はステップ内でスレッドのデフォルト値を参照していたブロックコードや計測は、今では各 `ContextVar`についてリクエストの値を参照します。executor が以前再バインドしていた固定セットだけではありません（`execution_id`, `remote_processing_times`, `apply_duration_minimum`、デバッグコレクター、ストリームセッション ID）。
* **ステップ内で設定されたコンテキストは、リクエスト間で漏れなくなりました** 各タスクのスナップショットはタスク完了時に破棄されるため、共有スレッドプール内で再利用されたワーカースレッドが以前のリクエストの `ContextVar` 状態を保持することはできません。以前は、その後の `run(...)` が同じプール上で、前のリクエストの値を観測してしまうことがありました（例：リモート GPU タイミングのエントリが以前のリクエストのコレクターに蓄積される）。
* **バッチ形状およびリスト形状のデータが、Modal のリモート実行境界をそのまま通過するようになりました** `Batch[...]` リモートで実行される Custom Python ブロックへの入力と、リスト形状のステップ結果は、両方のリモート転送先でバッチインデックスを保持したまま正しくシリアライズ／デシリアライズされるようになりました（roboflow/inference#2870）。

***

## Execution Engine `v1.15.0` | inference `1.3.9`

* **リモートの HTTP 501 エラーは内部 URL を露出させずにステータスを保持します** — リモートで実行された Workflow ステップが HTTP 501 を返した場合、Execution Engine は内部の producer URL を含む汎用の HTTP 500 ではなく、同じステータスと API メッセージを持つクライアント起因の Workflow エラーを返すようになりました。

## Execution Engine `v1.14.0` | inference `1.3.8`

**何が変わったか**

* **出力シリアライゼーションは文字列として宣言された種類を受け入れます** — 出力の種類がプレーンな文字列（例： `"string"`）として宣言されていた場合、 `Kind` オブジェクトではなく、出力シリアライゼーションが `TypeError: unhashable type: 'list'`でクラッシュし、ワークフロー全体が HTTP 500 になっていました。これらの種類は名前で解決されるようになったため、対応するシリアライザが適用されます（その種類に対するシリアライザが登録されていない場合は、元の値がそのまま通過します）。
* **ブロックは依存リソースを宣言できます** — `WorkflowBlockManifest` にインスタンスメソッド `discover_dependent_resources() -> Optional[List[DependentResource]]` が追加され、解析済みのステップが実行で使用する外部リソースを宣言できるようになりました。これにより、呼び出し元（プラットフォーム、プリロード、および認証の事前確認ツール）は、ワークフロー定義からそれらを静的に列挙できます。エンベロープは Execution Engine によって管理されます。リソース型 `roboflow_platform_model`, `roboflow_platform_project` および `third_party_model`は、それぞれ型付きでシリアライズ可能な（pydantic）メタデータエンティティを持ちます。プラットフォームモデルのエントリには、使用の性質も追加で示されます： `required_action` (`access` — モデルエンティティがプラットフォーム上で到達可能である必要があるだけ、対して `execution` — モデルが実行される）および、実行については `execution_location` (`local` / `remote` / `environment_defined` — ローカリティが実行時に `WORKFLOWS_STEP_EXECUTION_MODE`によって決定される場合。独自のローカリティ上書きで管理されるブロックは、その場でそれを指示します — SAM3 画像ブロックは、 `SAM3_EXEC_MODE=remote` のときは何も宣言せず（プロキシ実行では設定されたモデル ID を無視し、固定の SAM3 をサーバー側で実行）、 `environment_defined` それ以外では宣言します。 `None` （デフォルト）を返すと、そのブロックは依存関係を宣言しないことを意味します — `[]`とは異なり、外部リソースが不要であることを宣言します。ワークフローセレクターであるフィールド値（`$inputs.<name>` / `$steps.<name>.<property>`）はそのまま報告されます。各メタデータエンティティは `requires_runtime_resolution()` を公開し、そのような参照を具体的な識別子と区別します。フィールド値から最終 ID が生成される宣言（ `clip/<version>`のようなファミリ接頭辞、カタログ検索）には、置換された入力値を実行対象の ID に変換するシリアライズ不可能な `model_id_resolver` callable も追加されます。これはシリアライゼーション、JSON スキーマ、等価性から除外されます。モデル、Roboflow プロジェクト、またはサードパーティのホスト型モデルを参照するすべてのコアブロックがこのメソッドを実装しており、各実装は `run()` が実際に読み込むモデル識別子（バージョンフィールドから生成された ID を含む。例： `clip/<version>`）を反映します。プロジェクト宣言は、その有効化制御に従います。これは静的なマニフェスト値から決定されます。Roboflow モデルブロックは、 `disable_active_learning` が文字通り `True` （デフォルト）のときにアクティブラーニングの対象を除外し、データセットアップロードブロックは、 `disable_sink` が文字通り `True`のときは何も宣言しません。セレクター由来の制御は、保守的な may-need 宣言を維持します。イントロスペクションは `active_learning_target_dataset` プロパティで停止します — 明示的なターゲットなしにアクティブラーニングが有効な場合、モデル ID からプロジェクトは導出されません。モデルマネージャーの外でモデル重みを読み込むブロック（ `AutoModel.from_pretrained`を使用する SAM2/SAM3 ビデオトラッカー）は、現時点では意図的にこのメソッドを実装しません — それらの依存関係は未宣言のままです（`None`).
* **Dynamic（カスタム Python）ブロックは不明な依存関係を報告します** — 動的ブロック用に生成されたマニフェストは `None` を `discover_dependent_resources()`から返します。Python 本体は静的解析に対して不透明なので、「不明」だけが正直な答えです。
* **エンジン初期化時に宣言済みの Roboflow モデルを任意で事前読み込み** — `ExecutionEngine.init(...)` は新しい任意パラメータ `dependencies_pre_init` を受け付けます（デフォルト `None`）：事前読み込みする依存リソース型名のリストで、現時点でサポートされる値は `roboflow_platform_model` のみです。有効化されると、エンジンはコンパイル済みのすべてのステップの宣言済み依存関係（`deduce_blocks_dependencies` を compiler utils で）を推定し、実行用に宣言されたすべての具体的な Roboflow プラットフォームモデルをモデルマネージャーに登録します（どちらも `init_parameters`から取得され、API キーも同様です）。これは `init()` 中に行われます — 最初の実行前に行うことで、初回推論のレイテンシーを予測可能にします。 `$inputs.<name>` を参照する宣言は init 時に読み込めません。 **最初の** `run()` 1 回のみです — 実行時入力の検証後に行うため、無効なリクエストは単一の試行を消費せず、ダウンロードも引き起こしません — エンジンは提供されたランタイムパラメータ（入力のデフォルトを適用）に対してそれらを解決し、（添付されている場合は）宣言の `model_id_resolver` を適用します（たとえば、置換された CLIP バージョンは `clip/<version>`を事前読み込みし、実際に実行で使う ID と完全に一致させます）、そして識別子が具体化されたモデルを登録します。resolver が `None` を返す場合、その置換値は静的には解決不可能であることを宣言します（たとえば、Qwen の微調整済みセントネルラベルのように、最終 ID が別の入力に依存するもの）— 依存関係はスキップされ、実行時に解決されます。resolver が扱えない送信済み入力値（たとえば不明なカタログラベル）は `RuntimeInputError`を発生させます。登録は各ブロックの実際のローダーを反映します。宣言にはシリアライズ不可能な `model_registration_kwargs` を含めることができます（例： `endpoint_type=CORE_MODEL` を CLIP / OCR / SAM2 / YOLO-World スタイルのコアモデルに使う場合で、 `load_core_model()`に一致します）。各事前読み込みパスの後、エンジンは登録されたモデルが引き続きモデルマネージャー内に存在することを検証し、サイズ／メモリ制限付きマネージャーによって一部が追い出された場合は警告をログに記録します（それらは実行時に遅延ロードされます）。事前読み込みは、実効的なステップ実行モード（明示的な `step_execution_mode` init パラメータ、または `WORKFLOWS_STEP_EXECUTION_MODE` デフォルト）に従います： `environment_defined` 宣言はステップがローカルで実行される場合にのみ事前読み込みされ、 `local` 宣言は常に事前読み込みされます。一方、アクセスのみの宣言（重みは読み込まれない）、リモート実行、および `$steps.…`由来の識別子は事前読み込みされません。 `InferencePipeline.init_with_workflow(...)` は、これを任意指定の `workflows_dependencies_pre_init` パラメータとして公開します（デフォルト `None` — 事前読み込みなし）— 動画処理は予測可能な起動の恩恵が最も大きいです。

## Execution Engine `v1.13.0` | inference `v1.3.7`

**何が変わったか**

* **オフラインモードはリモートの Workflow ステップ実行を拒否します** — `OFFLINE_MODE` が有効なとき、コンパイラは `StepExecutionMode.REMOTE` をステップ初期化中に拒否します（`WorkflowEnvironmentConfigurationError`）そのため、Workflows はネットワーク接続なしでリモート推論クライアントを開けません。ローカルのステップ実行は、ウォーム済みキャッシュに対して引き続き動作します。
* **適切なモデルアクセス失敗ステータスコード** - ローカルのワークフローモデルの読み込み中に発生したモデルアクセス失敗では、HTTP 402、403、423 のステータスが保持され、汎用の HTTP 500 エラーとして表示されなくなりました。

## Execution Engine `v1.12.0` | inference `v1.3.2`

**何が変わったか**

**遅延解決** - 一部のステップは現在、 `Future` オブジェクトを出力する場合があり、クライアントが出力を必要とするまで出力解決を延期します。下流ブロックに対しては、これらの future は [step\_input\_assembler](https://github.com/roboflow/inference/blob/main/workflows/roboflow_workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py) で解決され、出力構築については [output\_constructor](https://github.com/roboflow/inference/blob/main/workflows/roboflow_workflows/execution_engine/v1/executor/output_constructor.py) で座標変換とともに解決されます。

## Execution Engine `v1.11.0` | inference `v1.3.1`

**何が変わったか**

* **辞書型ステップセレクターのケースごとの実行分岐** - フロー制御ブロックが `Dict[str, StepSelector]` プロパティ内でステップセレクターを宣言している場合（ `List[StepSelector]`ではなく）、コンパイラは辞書キーごとに別個の実行分岐を作成するようになりました。以前は単一プロパティ内のすべてのセレクターが 1 つの分岐を共有していたため、ブロックは各ターゲットへ独立してルーティングできませんでした。分岐名には現在、辞書キーが含まれます（例： `Branch[$steps.switch -> cases[red]]`）。リストプロパティ（たとえば `next_steps`）に保持されたセレクターは以前の共有分岐動作を維持するため、既存のブロックには影響しません。この変更により、新しい `roboflow_core/switch_case@v1` ブロックが可能になります（`graph_constructor.establish_control_flow_edge`).
* **修正: 繰り返し分岐名を持つ非 SIMD フロー制御マスク** - 1 つのリストプロパティを通じて 2 つ以上のターゲットを選択した非 SIMD フロー制御ステップで、 `Attempted to re-register maks for execution branch`が発生していました。分岐マスクの登録では、登録前に分岐名を重複排除するようになり、このクラッシュを修正しました（例： `ContinueIf` が複数ある場合に影響）。 `next_steps`; `execution_data_manager.manager._register_control_flow_output_for_non_simd_step`).

## Execution Engine `v1.10.1` | inference `v1.2.12`

**何が変わったか**

* **ネストされた内側ワークフロー内の動的ブロック** - コンパイラは現在、 `dynamic_blocks_definitions` をルートワークフローと、すべてのネストされた `inner_workflow` 子孫（深さ優先）から収集し、 `manifest.block_type` で重複排除し（最初の出現を採用し、重複がスキップされたときは警告をログに記録）、マージされたリストをルート定義へ `compile_dynamic_blocks` およびインライン化の前に持ち上げます。ネストされたワークフロー仕様でのみ定義されたカスタム Python ブロック型を使用する子ステップは、インライン化後に正しくコンパイルおよび実行されます。

## Execution Engine `v1.10.0` | inference `v1.2.10`

**何が変わったか**

* 値が静的値とセレクターの混在になっている辞書を認識する機能を追加しました。以前のバージョンでは、キーからセレクターへのマッピングだけが認識されており、実行時に一部のブロックが参照先の値へ正しく配線されないことがありました。変更は非破壊的ですが、過去に壊れていた特定のブロックを修正します。

## Execution Engine `v1.9.0` | inference `v1.2.0`

{% hint style="info" %}
**新機能: コンパイル時インライン化によるネストされたワークフロー**

このリリースでは **`roboflow_core/inner_workflow@v1`** ブロックが追加され、ワークフローが別のワークフロー定義を埋め込めるようになりました（インライン JSON、または `workflow_workspace_id` / `workflow_id` / optional `workflow_version_id`から解決）。子の入力は **`parameter_bindings`** で親から配線されます（子 `inputs[].name` → 親セレクター）。コンパイル時にエンジンはネストされたステップを親グラフへ **インライン化し** 、実行は通常のステップと同じ経路を使います（別個のネストされたランタイムはありません）。
{% endhint %}

**何が変わったか**

* **Inner workflow block** - 新しいフロー制御ブロック型 `roboflow_core/inner_workflow@v1` が `roboflow_core`に登録されます。親の出力は、インライン化がセレクターを書き換えるまで、子ワークフローの JsonField 出力を `$steps.<inner_step_name>.<child_output_name>` として参照できます。
* **コンパイルパイプライン** - ルート定義を解析する前に、コンパイラは次を行います：（1）参照を **正規化し** ます（デフォルト: Roboflow API + `workflows_core.api_key`、またはカスタム `workflows_core.inner_workflow_spec_resolver`), (2) **を使用）、（2）構成を検証し** （非巡回性、最大ネスティング深度、最大内側ワークフロー数）、（3）すべての内側ワークフローステップを通常のステップへ **インライン化し** インライン化してから、解析、ワークフロー仕様の検証、実行グラフ構築を続けます。
* **制限（環境変数）** - `WORKFLOWS_MAX_INNER_WORKFLOW_DEPTH` を受け付けます（デフォルト `4`）はルートからの包含深度を上限します。 `WORKFLOWS_MAX_INNER_WORKFLOW_COUNT` を受け付けます（デフォルト `32`）はネストされた定義内の `inner_workflow` ステップの総数を上限します。
* **ドキュメント** - 参照： [Inner workflows (nested definitions)](/workflows/ja/gaido/developer-guide/inner-workflows.md) 使用法、バインディング、制限、例について。

## Execution Engine `v1.8.0` | inference `v1.1.1`

{% hint style="info" %}
**付加的な変更 + 最小限の影響が想定されるバグ修正による 1 つの破壊的変更**

このリリースでは Execution Engine が拡張され、制御フローによってゲートされるステップ（たとえば `ContinueIf` ブロックの後など）は、 **データ由来のリネージがない** 場合、つまり上流ステップからバッチ指向の入力を受け取らない場合でも実行できるようになりました。リネージと実行次元は、制御フローの前段ステップから導出できるようになりました。既存のワークフローには影響しません。

導入された破壊的変更の 1 つは、 `Batch.remove_by_indices` がネストされたバッチに対して持つバグ修正によるものです（下記参照）。影響は最小限と見込まれます。
{% endhint %}

**何が変わったか**

* **制御フローのリネージ** - コンパイラは現在、制御フローステップから来るリネージ（例： `ContinueIf`の後の分岐）を追跡します。新しい概念である **control flow lineage support** は、ステップにバッチ指向のデータ入力がなく、制御フローステップが前段にある場合に使用されます。その場合、ステップの実行スライスとバッチ構造は、それらの制御フロー前段から取得されます。
* **互換性チェックの緩和** - 以前は、 `verify_compatibility_of_input_data_lineage_with_control_flow_lineage` が `ControlFlowDefinitionError` を、制御フローの前段はあるがデータ由来のリネージがない任意のステップに対して発生させていたため、そのようなステップはコンパイルできませんでした。そのチェックは現在緩和され、入力データのリネージがない場合は互換性を強制せず、ステップのリネージは代わりに制御フロー前段ステップのリネージから導出されます。厳格なチェックは、ステップが *実際に* データ由来のリネージを持つ場合には引き続き実行され、制御フローとデータのリネージの互換性を保証します。
* **新しいステップパターン** - 制御フローによってのみトリガーされ、バッチデータを消費しないステップが、現在は正しく実行されます。たとえば、 `ContinueIf` の後にメール通知（または他の副作用を持つステップ）を送信でき、 `message_parameters`のようなパラメータにデータを配線する必要はありません。ステップは各制御フローブランチごとに 1 回実行され、リネージと次元性は制御ステップから取得されます。
* **`Batch.remove_by_indices` ネストされたバッチを伴う（動作修正）** - `Batch.remove_by_indices`によってインデックスを削除する際、ネストされた `Batch` 要素は同じインデックス集合で再帰的にフィルタされるようになりました。その結果、削除されたインデックスにあるエントリ（ `None` 値を含む）は、ネストされたバッチからも正しく除去されます。以前はトップレベルのバッチだけがフィルタされ、ネストされたバッチは変更されないままでした。

  既定では `WorkflowBlock`, `accepts_empty_values()`は `False`です。これがバイパスされていた間、そのような入力を消費するブロックは、たとえば `StitchDetectionsBatchBlock`:

  ```python
  def run(
      self,
      images: Batch[WorkflowImageData],
      images_predictions: Batch[Batch[sv.Detections]],
  ) -> BlockResult:
      result = []
      for image, image_predictions in zip(images, images_predictions):
          image_predictions = [deepcopy(p) for p in image_predictions if len(p)]
          for p in image_predictions:
              coords = p["parent_coordinates"][0]
      ...
  ```

  この変更の影響を受ける唯一のコアブロックは `DimensionCollapseBlockV1` ブロックです。これは None 値でフィルタせずに個々の入力をバッチに包んでいたためです。

  ```python
  class DimensionCollapseBlockV1(WorkflowBlock):

    @classmethod
    def get_manifest(cls) -> Type[WorkflowBlockManifest]:
        return BlockManifest

    def run(self, data: Batch[Any]) -> BlockResult:
        return {"output": [e for e in data]}
  ```

  このブロックの出力を使うと、下流のアプリケーションは、各値を自分でフィルタリングしない限り、完全に失敗するか、None値を黙って処理してしまう可能性があります。

  以上を踏まえると、影響は最小限だと考えています。

## Execution Engine `v1.7.0` | inference `v0.59.0`

{% hint style="warning" %}
**ワークフローにおけるステップエラーに関する破壊的変更**

の無効な HTTP レスポンスコードに関連するバグを修正するために `inference-server` のワークフロー実行リクエストの処理において、Execution Engine のエラー処理を担う既定の機構を変更する必要がありました。この変更により、Roboflow Hosted Platform および `inference>=0.59.0`では、Roboflow プラットフォームとやり取りする Workflow ブロックが、クライアント側の設定ミス（無効な Roboflow API キー、無効なモデル ID など）により失敗した場合、 `StepExecutionError` （およびサーバーからの HTTP 500 レスポンス）の代わりに `ClientCausedStepExecutionError` を送出するようになります（該当する HTTP レスポンスコードは 400、401、403、404 など）。
{% endhint %}

変更の影響を受けるシナリオ一覧:

* Roboflow モデルを使うブロックが無効なモデル ID を定義している場合 - これからは `ClientCausedStepExecutionError` ステータスコード 400 で
* Roboflow モデルを使うブロックが無効な API キーを定義している場合 - これからは `ClientCausedStepExecutionError` ステータスコード 401 で
* Roboflow モデルを使うブロックが無効な API キー、またはリソースにアクセスするための有効なスコープを持つキーが欠落している場合 - これからは `ClientCausedStepExecutionError` ステータスコード 403 で
* Roboflow モデルを使うブロックが存在しないモデルを定義している場合 - これからは `ClientCausedStepExecutionError` ステータスコード 404 で

{% hint style="info" %}
**復活 `レガシーの` エラー処理**

必要に応じて、レガシーのエラーハンドラ動作を復活させることができます。移行期間中には役立つかもしれません。そのために必要なのは、環境変数を設定することだけです。 `DEFAULT_WORKFLOWS_STEP_ERROR_HANDLER=legacy`.
{% endhint %}

## Execution Engine `v1.6.0` | inference `v0.53.0`

{% hint style="info" %}
**変更に注意が必要な場合があります**

このリリースでは、次を伴うアップグレードと新機能が導入されます: **既存のワークフローに変更は不要** です。一部のブロックは、最新の Execution Engine の機能を活用するためにアップグレードが必要になる場合があります。
{% endhint %}

以前の Execution Engine では、特定の種類のブロック、特に Single Instruction, Multiple Data（SIMD）モードで動作するブロックとやり取りする際に大きな制約がありました。これらのブロックは、入力のバッチをまとめて処理し、各要素に同じ操作を適用して、バッチ全体の結果を返すように設計されています。

例えば、 `run(...)` このようなブロックのメソッドは次のようになるかもしれません:

```python
def run(self, image: Batch[WorkflowImageData], confidence: float):
    pass
```

manifest では、 `image` フィールドはバッチを受け入れるものとして宣言されています。

問題は、入力画像がバッチで動作しないブロックから来る場合に発生しました。そのような場合、Execution Engine は個々の画像からバッチを構成できず、次のような苛立たしいコンパイルエラーにつながることがよくありました:

```
step `$steps.model` の property `images` にプラグインされた無効な参照を検出しました - その step property は 
バッチ指向の入力を厳密に必要としますが、入力セレクタには非バッチ指向の入力が含まれています - これは 
Workflow の構築に問題があることを示しています。通常、この問題は非バッチ指向の step input が 
非バッチ指向の step の出力、または非バッチ指向の入力で埋められているときに発生します。
```

Execution Engine では `v1.6.0`、この制約は削除され、次の動作が導入されました:

* ある入力がバッチ指向でなければならないと検出されると、 **Auto Batch Casting** と呼ばれる手順が適用されます。これにより、入力は自動的に `Batch[T]`に変換されます。すべてのバッチモード入力は manifest で既に明示的に示されているため、ほとんどのブロック（下記に挙げる例外を除く）は、内部変更なしでこのアップグレードの恩恵を受けられます。
* auto-batch cast パラメータの次元数（ネストのレベル）は、ワークフロー内の特定のブロックのコンテキストおよびその manifest に基づいて、コンパイル時に決定されます。ほかのバッチ指向の入力が存在する場合（ *lineage supports*と呼びます）、Execution Engine は auto-cast されたバッチを構築するときの参照としてそれらを使用します。これにより、各バッチ次元の要素数が step に供給される他のデータと一致することが保証されます（実際のバッチ入力が与えられた場合にアサートされるはずだった内容をシミュレートします）。 *lineage supports*が存在しない場合、またはブロックの manifest がそれを要求する場合（たとえば入力次元オフセットが設定されている場合）、不足している次元は [`torch.unsqueeze(...)` 操作](https://docs.pytorch.org/docs/stable/generated/torch.unsqueeze.html).
* その後、step の出力は Auto Batch Casting コンテキストの有無に対して評価されます。評価に基づいて、出力はバッチまたはスカラーとして保存され、キャストの効果が局所的に保たれます。唯一の例外は、ブロック自身によって導入される出力次元数の変更です。副作用として、次のことが可能になりました:
  * **スカラーから出力バッチを作成する** （step が次元数を増やす場合）、および
  * **バッチをスカラーに縮約する** （ブロックが次元数を減らす場合）。
* 潜在的な摩擦点は2つあります。まず **バッチを受け入れないブロックで** （したがってバッチ受け入れ入力を明示しない） **出力次元数を減らす場合です**。以前のバージョンでは、Execution Engine は次元ラッピングを適用してこれを処理していました。すべてのバッチ指向入力は追加の `Batch[T]` 次元でラップされ、ブロックの `run(...)` メソッドがリスト次元に対して reduce 操作を実行できるようにしていました。しかし Auto Batch Casting では、そのようなブロックは、特定の入力がスカラーなのかバッチなのかについて Execution Engine に明確なシグナルを与えなくなるため、キャストが非決定的になります。これに対処するため、新しい manifest メソッドが導入されました: `get_parameters_enforcing_auto_batch_casting(...)`このメソッドは、次元数が減少する際にバッチキャストを強制すべきパラメータの一覧を返さなければなりません。ほかの文脈で使うことは想定されていません。

{% hint style="warning" %}
**新しいメソッドが既存のブロックに与える影響**

定義する要件 `get_parameters_enforcing_auto_batch_casting(...)` 上記のケースで Auto Batch Casting 機能を完全に使うためのメソッドは、厳密ではありません。ブロックを変更しない場合、唯一の影響は、以前は **失敗していた** ワークフローが、コンパイルエラーでは動作するか、あるいは **実行時エラー**で失敗するかのどちらかになることです。これはブロックの `run(...)` メソッド実装の詳細に依存します。
{% endhint %}

* 2つ目の摩擦点は、 `get_parameters_accepting_batches_and_scalars(...)` を使って、バッチとスカラーの両方をサポートする入力フィールドを宣言しているブロックがある場合に発生します。既定では、Execution Engine はそのようなパラメータに対して auto-casting をスキップします。なぜなら、このメソッドは歴史的に **ブロック自身がスカラーをバッチへブロードキャストできる能力を持つことを宣言する方法として、常に存在していたからです。** — 参照 [の実装 `roboflow_core/detections_transformation@v1`](https://github.com/roboflow/inference/blob/main/workflows/roboflow_workflows/core_steps/transformations/detections_transformation/v1.py) ブロック。ある意味で、Auto Batch Casting は *冗長* なので、それらのブロックはそのままにして、代わりに新しいバージョンのそのようなブロックでは `get_parameters_enforcing_auto_batch_casting(...)` の代わりに `get_parameters_accepting_batches_and_scalars(...)` を使うよう更新することを提案します。
* 以前のバージョンでは、厳しい制約がありました。次元数の縮約はレベル 2 以上でしか起こせませんでした（つまり、ネストされたバッチでのみ）。この制限は現在では削除されています。次元数縮約ブロックはスカラーでも動作でき、出力次元数はゼロ境界で「跳ね返る」ようになります。

1つ **重要な変更があります。出力の構築方法です。** 以前の Execution Error では、ブロックが `Batch[X]` を最初の次元レベルで直接生成することは許可されていませんでした。その領域は入力バッチへのマッピング用に予約されていたためです。version `v1.6.0`以降、この制限は削除されました。

以前は、出力は常に要素のリストとして返されていました:

* 入力バッチに対応する形、または
* 入力がスカラーのみの場合は単一要素のリスト。

ここで疑問が生じます。ブロックが最初の次元レベルでバッチを生成するようになったら、どうなるべきでしょうか？単純に `zip(...)` で入力ベースの出力と組み合わせることはできません。なぜなら、新たに生成されたバッチのサイズが入力要素数と一致しない可能性があり、操作が曖昧になるからです。

これを解決するため、次の規則を採用しました:

* サイズ 1 の **"ダミー" 入力バッチ**.
* が存在するとみなして状況を扱う。
* スカラー入力から生成されたすべてのバッチは、見かけより 1 レベル深いものとして扱います。
* 実行の結果、入力バッチが消失することはありますが、その際に新しい第1レベル次元が現れても、出力の一貫性を保つために、仮想的には引き続きネストされたものとして扱われます。

**例:**

```
(入力なし)    IMAGE FETCHER BLOCK --> image --> OD MODEL --> predictons --> CROPS --> 出力は: ["crops": [<crop>, <crop>, ...]] 
```

重要なのは **、以前に作成された有効なワークフローから生成された結果は同じままであり** 、変更の影響を受けるのは新しい機能を利用するために作成された新規ワークフローのみだということです。

### 移行ガイド

<details>

<summary>`get_parameters_enforcing_auto_batch_casting(...)` メソッドの追加</summary>

出力次元数を減らし、バッチ指向入力を定義しないブロックは、実装が `Batch[T]` という block manifest の新しい class method により `get_parameters_enforcing_auto_batch_casting(...)`

```python
from typing import List, Literal, Type, Union

import supervision as sv

from inference.core.utils.drawing import create_tiles
from inference.core.workflows.execution_engine.entities.base import (
    Batch,
    OutputDefinition,
    WorkflowImageData,
)
from inference.core.workflows.execution_engine.entities.types import (
    IMAGE_KIND,
    OBJECT_DETECTION_PREDICTION_KIND,
    Selector,
)
from inference.core.workflows.prototypes.block import (
    BlockResult,
    WorkflowBlock,
    WorkflowBlockManifest,
)

class BlockManifest(WorkflowBlockManifest):
    type: Literal["my_plugin/tile_detections@v1"]
    crops: Selector(kind=[IMAGE_KIND])
    crops_predictions: Selector(
        kind=[OBJECT_DETECTION_PREDICTION_KIND]
    )
    scalar_parameter: Union[float, Selector()]

    @classmethod
    def get_output_dimensionality_offset(cls) -> int:
        return -1

    @classmethod
    def get_parameters_enforcing_auto_batch_casting(cls) -> List[str]:
        return ["crops", "crops_predictions"]

    @classmethod
    def describe_outputs(cls) -> List[OutputDefinition]:
        return [
            OutputDefinition(name="visualisations", kind=[IMAGE_KIND]),
        ]

class TileDetectionsBlock(WorkflowBlock):

    @classmethod
    def get_manifest(cls) -> Type[WorkflowBlockManifest]:
        return BlockManifest

    def run(
        self,
        crops: Batch[WorkflowImageData],
        crops_predictions: Batch[sv.Detections],
        scalar_parameter: float,
    ) -> BlockResult:
        print("これは自動バッチキャストの対象にならないパラメータです！", scalar_parameter)
        annotator = sv.BoxAnnotator()
        visualisations = []
        for image, prediction in zip(crops, crops_predictions):
            annotated_image = annotator.annotate(
                image.numpy_image.copy(),
                prediction,
            )
            visualisations.append(annotated_image)
        tile = create_tiles(visualisations)
        return {"visualisations": tile}
```

* の行で `34-36` 強制的な auto-batch casting の対象となるフィールドの宣言を追加する必要があります
* 上記の結果として、run メソッドの入力パラメータ（行 `53-54`）は `Batch[T]` Execution Engine によって

</details>

## Execution Engine `v1.5.0` | inference `v0.38.0`

{% hint style="info" %}
**変更に対処は不要**

この変更は Workflows の利用者側での変更を必要としません。これは単なる性能最適化です。
{% endhint %}

* の init メソッドに新しいパラメータを追加しました `BaseExecutionEngine` クラス - `executor` で、Python の `ThreadPoolExecutor` のインスタンスを受け取れるようにし、Execution Engine がそれを使用できます。この変更により、各 `BaseExecutionEngine.run(...)` ごとに専用の `ThreadPoolExecutor` インスタンスを必要としなくなるため、処理はより高速になるはずです。さらに、スレッド生成を大幅に制限しているため、一部の環境ではその点でも利点があります。
* 変更があっても、Execution Engine は同時に実行される step の上限を維持します。つまり、一度に executor を通る step 数を制限しています（Execution Engine はもはや `ThreadPoolExecutor` の生成を制御しておらず、pool により多くの worker を用意できるためです）。

<details>

<summary>ThreadPoolExecutor を Execution Engine に注入する方法</summary>

```python
from concurrent.futures import ThreadPoolExecutor
workflow_init_parameters = { ... }
with ThreadPoolExecutor(max_workers=...) as thread_pool_executor:
    execution_engine = ExecutionEngine.init(
        init_parameters=workflow_init_parameters,
        max_concurrent_steps=4,
        workflow_id="your-workflow-id",
        executor=thread_pool_executor,
    )
    runtime_parameters = {
      "image": cv2.imread("your-image-path")
    }
    results = execution_engine.run(runtime_parameters=runtime_parameters)
```

</details>

## Execution Engine `v1.4.0` | inference `v0.29.0`

* 新しい kind を追加 - [`secret`](/workflows/ja/gaido/developer-guide/kinds/secret.md) を資格情報の表現に使用します。 **対応不要** です。ただし、今後はブロック開発者が、ブロックがパラメータとして secret 値を受け取る必要がある場合、この kind を使うべきだと期待されています。
* で導入された結果シリアライズの問題を修正 `v1.3.0`  - うっかり、Execution Engine は非バッチ指向の出力をシリアライズしていませんでした。
* ステップの入力を準備する際の Execution Engine のバグを修正しました。以前は non-SIMD ステップについて、runtime で入力を収集する際に、 `WorkflowBlockManifest.accepts_empty_input()` メソッドの結果が無視されており、1つの non-SIMD ステップが下流ブロックに空の値を渡したときにバグが発生していました。さらに、 `v1.3.0`で行われた変更により、non-SIMD ブロックが下流の SIMD ステップに入力を簡単に渡せるようになったため、上流の non-SIMD ブロックが空でない結果を返したかどうかを確認する必要があります（SIMD ブロックは空の結果を受け付けない場合があるため）。この確認を追加しました。 **対応不要** 既存のブロックには必要ですが、この修正によって以前壊れていた Workflows が修復される可能性があります。

## Execution Engine `v1.3.0` | inference `v0.27.0`

* 各 kind に serializer と deserializer を定義できるようにする変更を導入しました。この変更により、Workflows プラグインと Execution Engine の結合が緩み、データ転送をワイヤ経由で必要とする外部システムとエコシステムを統合できるようになります。 [ブロックのバンドリング](/workflows/ja/gaido/developer-guide/block-bundling.md) ページはその変更を反映して更新されました。
* *種別* で定義された `roboflow_core` plugin には適切な serializer と deserializer が与えられました
* Workflows Compiler と Execution Engine は **任意の&#x20;*****kind***&#x306E;バッチ指向入力をサポートするように強化されました。これに反して、以前のバージョンでは `v1.3.0`、バッチ指向入力として受け取れたのは `image` および `video_metadata` kind と内部データ形式の不幸で不要な結合が **Execution Engine のレベルで導入された**）。その結果、
  * **新しい入力型が導入されました:** `WorkflowBatchInput` は、これ以降バッチ指向入力を表すために使用されるべきです（そしてそれらを `WorkflowParameters`). `WorkflowBatchInput` から明確に分離します）。これにより、ユーザーはデータの [*kind*](/workflows/ja/gaido/developer-guide/kinds.md) とその [*次元数*](/workflows/ja/gaido/developer-guide/workflow-execution.md#steps-interactions-with-data)の両方を定義できるようになります。新しい入力型は、実質的に以前のすべてのバッチ指向入力のスーパーセットです: `WorkflowImage` および `WorkflowVideoMetadata`、これらは **引き続きサポートされます**が、 **Execution Engine の `v2`**&#x3067;削除される予定です。新しい入力形式への調整をお勧めしますが、現時点では要件は厳格ではありません。というのも、現在 Execution Engine は入力データの明示的な定義を必要としており *kind* 、適切なデータデシリアライザを選択するためです。将来的にはそうならないかもしれません。多くの場合、バッチ指向データは *kind* コンパイラによって推定できる可能性があるからです（ただし、この機能は現時点では実装されていません）。
  * **新しい selector 型注釈が導入されました** — 単に `Selector(...)`. `Selector(...)` と呼ばれ、 `StepOutputSelector`, `WorkflowImageSelector`, `StepOutputImageSelector`, `WorkflowVideoMetadataSelector` および `WorkflowParameterSelector` を置き換えることを意図しています。block manifests では、これにより開発者は、特定の step manifest property が特定の *kind*の selector を保持できることを表現できます。前述の旧注釈タイプは **非推奨と見なすべきであり**、 `Selector(...)`.
  * selector 型注釈の簡素化の結果、旧 selector は block のどのパラメータが `run(...)` メソッドにより Execution Engine からラップされた状態で提供されるかという情報をもはや与えなくなります [`Batch[X]` コンテナ](/workflows/ja/gaido/developer-guide/data-representations.md#batch)。旧 selector 型注釈と `block_manifest.accepts_batch_input()` メソッドの代わりに、バッチ指向データで供給されることが期待されるパラメータ（`block_manifest.get_parameters_accepting_batches()`）と、両方を受け取れるパラメータ（ *バッチ* および *スカラー* 値（`block_manifest.get_parameters_accepting_batches_and_scalars()`）。の2つのメソッドへ切り替えることを提案します。 `block_manifest.accepts_batch_input()` の戻り値は、2つの新しいメソッドの結果の上に構築されます。変更は **破壊的ではありません**。というのも、バッチを処理できた既存のブロックは、必ず `block_manifest.accepts_batch_input()` メソッドを実装して `True` を返し、バッチ指向データを示す適切な selector 型注釈を使用していたはずだからです。
* これらの変更の結果、今では **任意のワークフローを複数のワークフローに分割し、step のサブセットを実行することが可能になりました**。これにより、デバッガのようなツールを構築できます。

**破壊的変更の予定 - Execution Engine `v2.0.0`**

* `WorkflowImage` および `WorkflowVideoMetadata` の inputs は Workflows エコシステムから削除されます。
* `StepOutputSelector,` WorkflowImageSelector`,` StepOutputImageSelector`,` WorkflowVideoMetadataSelector`および`WorkflowParameterSelector\` 型注釈は block manifests から Workflows エコシステムに削除されます。{% endhint %}

### 移行ガイド

<details>

<summary>Kinds の serializer と deserializer</summary>

Workflows プラグインを作成する際、Workflows の *kind*に対して独自の serializer と deserializer を導入できます。そのためには、単に次の辞書をプラグインのメインモジュール（ `load_blocks(...)` 関数を置くのと同じ場所）に配置してください:

```python
from typing import Any

def serialize_kind(value: Any) -> Any:
  # ここに、次のために使用されるコードを配置します
  # 内部の Workflows データ表現を次に変換します 
  # JSON でワイヤ経由で送信できる外部のものを使用して
  # Python のデフォルト JSON エンコーダ）。
  pass

def deserialize_kind(parameter_name: str, value: Any) -> Any:
  # ここに、デコードに使用されるコードを置く 
  # ワイヤ経由で Execution Engine に送信されたデータを
  # そして、それを適切な内部の Workflows データ表現へ変換する
  # ブロックが理解できるもの。
  pass

KINDS_SERIALIZERS = {
    "name_of_the_kind": serialize_kind,
}
KINDS_DESERIALIZERS = {
    "name_of_the_kind": deserialize_kind,
}
```

</details>

<details>

<summary>セレクタ向けの新しい型注釈 - `Batch[X]` 入力のないブロック</summary>

Blocks manifest は **任意で** 更新して `Selector` 以下のようにできます:

```python
from typing import Union
from inference.core.workflows.prototypes.block import WorkflowBlockManifest
from inference.core.workflows.execution_engine.entities.types import (
    INSTANCE_SEGMENTATION_PREDICTION_KIND,
    OBJECT_DETECTION_PREDICTION_KIND,
    FLOAT_KIND,
    WorkflowImageSelector,
    StepOutputImageSelector,
    StepOutputSelector,
    WorkflowParameterSelector,
)

class BlockManifest(WorkflowBlockManifest):

    reference_image: Union[WorkflowImageSelector, StepOutputImageSelector]
    predictions: StepOutputSelector(
        kind=[
            OBJECT_DETECTION_PREDICTION_KIND,
            INSTANCE_SEGMENTATION_PREDICTION_KIND,
        ]
    )
    confidence: WorkflowParameterSelector(kind=[FLOAT_KIND]) 
```

は単に次のように変更されるべきです:

```python
from inference.core.workflows.prototypes.block import WorkflowBlockManifest
from inference.core.workflows.execution_engine.entities.types import (
    INSTANCE_SEGMENTATION_PREDICTION_KIND,
    OBJECT_DETECTION_PREDICTION_KIND,
    FLOAT_KIND,
    IMAGE_KIND,
    Selector,
)

class BlockManifest(WorkflowBlockManifest):
    reference_image: Selector(kind=[IMAGE_KIND])
    predictions: Selector(
        kind=[
            OBJECT_DETECTION_PREDICTION_KIND,
            INSTANCE_SEGMENTATION_PREDICTION_KIND,
        ]
    )
    confidence: Selector(kind=[FLOAT_KIND]) 
```

</details>

<details>

<summary>セレクタ向けの新しい型注釈 - `Batch[X]` 入力のあるブロック</summary>

Blocks manifest は **任意で** 更新して `Selector` 以下のようにできます:

```python
from typing import Union
from inference.core.workflows.prototypes.block import WorkflowBlockManifest
from inference.core.workflows.execution_engine.entities.types import (
    INSTANCE_SEGMENTATION_PREDICTION_KIND,
    OBJECT_DETECTION_PREDICTION_KIND,
    FLOAT_KIND,
    WorkflowImageSelector,
    StepOutputImageSelector,
    StepOutputSelector,
    WorkflowParameterSelector,
)

class BlockManifest(WorkflowBlockManifest):

    reference_image: Union[WorkflowImageSelector, StepOutputImageSelector]
    predictions: StepOutputSelector(
        kind=[
            OBJECT_DETECTION_PREDICTION_KIND,
            INSTANCE_SEGMENTATION_PREDICTION_KIND,
        ]
    )
    data: Dict[str, Union[StepOutputSelector(), WorkflowParameterSelector()]]
    confidence: WorkflowParameterSelector(kind=[FLOAT_KIND]) 

    @classmethod
    def accepts_batch_input(cls) -> bool:
        return True
```

は次のように変更されるべきです:

```python
from inference.core.workflows.prototypes.block import WorkflowBlockManifest
from inference.core.workflows.execution_engine.entities.types import (
    INSTANCE_SEGMENTATION_PREDICTION_KIND,
    OBJECT_DETECTION_PREDICTION_KIND,
    FLOAT_KIND,
    IMAGE_KIND,
    Selector,
)

class BlockManifest(WorkflowBlockManifest):
    reference_image: Selector(kind=[IMAGE_KIND])
    predictions: Selector(
        kind=[
            OBJECT_DETECTION_PREDICTION_KIND,
            INSTANCE_SEGMENTATION_PREDICTION_KIND,
        ]
    )
    data: Dict[str, Selector()]
    confidence: Selector(kind=[FLOAT_KIND]) 

    @classmethod
    def get_parameters_accepting_batches(cls)W -> List[str]:
        return ["predictions"]

    @classmethod
    def get_parameters_accepting_batches_and_scalars(cls) -> List[str]:
        return ["data"]
```

以下を指摘してください:

* 元の例における `data` プロパティは、 **バッチ** のデータと **スカラー** 値の両方を受け取ることができました。これは、バッチ指向のデータ用セレクタ（`StepOutputSelector`) と *スカラー* データ（`WorkflowParameterSelector`）のおかげです。今では同じことが `Selector(...)` 型注釈と `get_parameters_accepting_batches_and_scalars(...)` メソッドの戻り値によって表現されています。

</details>

<details>

<summary>Workflows 定義における新しい入力</summary>

これまでに `WorkflowImage` または `WorkflowVideoMetadata` の入力を Workflows 定義で使用していた人は **任意で** 移行できます `WorkflowBatchInput`。移行の流れは以下のとおりです:

```json
{
  "inputs": [
    {"type": "WorkflowImage", "name": "image"},
    {"type": "WorkflowVideoMetadata", "name": "video_metadata"}
  ]
}
```

は次のように変更されるべきです:

```json
{
  "inputs": [
    {
      "type": "WorkflowBatchInput",
      "name": "image",
      "kind": ["image"]
    },
    {
      "type": "WorkflowBatchInput",
      "name": "video_metadata",
      "kind": ["video_metadata"]
    }
  ]
}
```

**空欄のままにすると `kind` フィールドを空にしておくと、画像のような一部のデータが正しくデシリアライズされない場合があります。**

**注意**

データがシリアライズされる方法が `roboflow_core` プラグイン内で気に入らない場合は、 *kind*関数をプラグインに登録して Execution Engine に読み込むことで、シリアライズ/デシリアライズの方法を自由に変更できます。最後に定義された serializer/deserializer が使用されます。

</details>

## Execution Engine `v1.2.0` | inference `v0.23.0`

* その [`video_metadata` kind](/workflows/ja/gaido/developer-guide/kinds/video-metadata.md) は非推奨となり、私たちは **今後のブロック構築ではその使用をやめることを強く推奨します**。代替として、 [`image` kind](/workflows/ja/gaido/developer-guide/kinds/image.md) は同じメタデータをサポートするよう拡張されました [`video_metadata` kind](/workflows/ja/gaido/developer-guide/kinds/video-metadata.md)をオプションで指定できるようになりました。この更新は **破壊的ではありません** 既存のブロックには **一部の古いブロックは** 画像を出力する **互換性がなくなる可能性があります** と **将来の** 動画処理ブロック。

<details>

<summary>ブロックの潜在的な非互換性</summary>

前述のとおり、 `video_metadata` の内部表現にオプションフィールドとして追加することは [`image` kind](/workflows/ja/gaido/developer-guide/kinds/image.md) (`WorkflowImageData` （クラス）を追加すると、既存のブロックが出力する [`image` kind](/workflows/ja/gaido/developer-guide/kinds/image.md) と、将来の動画処理ブロックが依存する `video_metadata` の一部であること `image` 表現。

問題は、 **デフォルトの** 値を `video_metadata` に `image` 入力から明示的にコピーしなくても提供できる一方で、上流で追加されたデフォルト以外のメタデータは失われる可能性があります。これは、 `video_metadata` それに依存する下流ブロックが期待どおりに動作しなくなる原因になります。

既存のすべての `roboflow_core` ブロックはこれに対応するよう更新しましたが、外部リポジトリでこの変更以前に作成されたブロックは、その出力画像が動画処理ブロックで使用されるワークフローで問題を引き起こす可能性があります。

</details>

* 非推奨となった [`video_metadata` kind](/workflows/ja/gaido/developer-guide/kinds/video-metadata.md) は引き続き使用できますが、Execution Engine のバージョン `v2.0.0`.

{% hint style="warning" %}
**破壊的変更の予定 - Execution Engine `v2.0.0`**

[`video_metadata` kind](/workflows/ja/gaido/developer-guide/kinds/video-metadata.md) で非推奨となり、 `v2.0.0`
{% endhint %}

* 上記の変更の結果、 [`image` kind](/workflows/ja/gaido/developer-guide/kinds/image.md) の内部表現は、新しい `video_metadata` プロパティを含むよう更新されました。このプロパティはコンストラクタで任意に設定できます。指定しない場合は、妥当なデフォルト値が使用されます。ブロック内でのメタデータ操作を簡単にするため、2 つの新しいクラスメソッドを導入しました: `WorkflowImageData.copy_and_replace(...)` および `WorkflowImageData.create_crop(...)`。詳細は、更新された [`WoorkflowImageData` 使用ガイド](/workflows/ja/gaido/developer-guide/data-representations.md#workflowimagedata).
