> 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/hi/developer-guide/developer-guide/execution-engine-changelog.md).

# Execution Engine परिवर्तन लॉग

नीचे आप Execution Engine के लिए परिवर्तन सूची पा सकते हैं।

## अप्रकाशित

**क्या बदला**

यहाँ उपयोगकर्ताओं को दिखाई देने वाले compile या execution व्यवहार परिवर्तनों को जोड़ें। रिलीज़ करते समय maintainers इस heading को Execution Engine और inference versions से बदल देते हैं।

***

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

**क्या बदला**

* स्थानीय workflow models लोड करते समय उठाई गई model-access विफलताएँ अब सामान्य HTTP 500 errors के रूप में दिखने के बजाय HTTP 402, 403, और 423 statuses को बनाए रखती हैं।
* **Step worker threads अब कॉलर का पूरा `contextvars` संदर्भ** समानांतर में निष्पादित steps (जिसमें via spawned nested block worker pools शामिल हैं `run_in_parallel`) submitting thread के संदर्भ के per-task snapshot के अंदर चलते हैं। Block code और instrumentation जो पहले step के अंदर thread-default values देखते थे, अब हर `ContextVar`के लिए request के values देखते हैं, केवल executor द्वारा पहले पुनः-बाउंड किए गए निश्चित set के लिए नहीं (`execution_id`, `remote_processing_times`, `apply_duration_minimum`debug collectors, stream session id).
* **एक step के अंदर सेट किया गया संदर्भ अब requests के बीच leak नहीं होता** हर task का snapshot task के समाप्त होने पर discard कर दिया जाता है, इसलिए shared thread pool में पुन: उपयोग हुआ worker thread `ContextVar` पिछले request की state को बनाए नहीं रख सकता। पहले बाद का `run(...)` उसी pool पर पिछले request के values देख सकता था (जैसे remote GPU-timing entries का पहले के request के collector पर जमा होना)
* **Batch- और list-आकार का data अब Modal remote-execution boundary को बिना टूटे पार करता है** `Batch[...]` दूरस्थ रूप से निष्पादित Custom Python blocks के inputs और list-आकार के step results अब दोनों remote transports पर सही ढंग से serialize और deserialize होते हैं, batch indices सुरक्षित रहते हैं (roboflow/inference#2870).

***

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

* **Remote HTTP 501 errors internal URLs उजागर किए बिना अपना status बनाए रखते हैं** — जब remotely executed Workflow step HTTP 501 लौटाता है, तो Execution Engine अब internal producer URL वाले generic HTTP 500 के बजाय उसी status और API message के साथ client-caused Workflow error दिखाता है।

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

**क्या बदला**

* **Output serialization string के रूप में घोषित kinds को स्वीकार करता है** — जब कोई output kind एक साधारण string के रूप में घोषित किया गया था (जैसे `"string"`) बजाय `Kind` object के, तो output serialization `TypeError: unhashable type: 'list'`के साथ crash हो जाती थी, और पूरा Workflow run HTTP 500 के रूप में दिखता था। ऐसे kinds अब नाम से resolve किए जाते हैं, इसलिए matching serializer लागू होता है (या जब उस kind के लिए कोई serializer registered न हो तो raw value पास-through हो जाती है)।
* **Blocks अपनी dependent resources घोषित कर सकते हैं** — `WorkflowBlockManifest` को एक instance method मिलता है `discover_dependent_resources() -> Optional[List[DependentResource]]` जो एक parsed step को वे external resources घोषित करने देता है जिनका उसका execution उपयोग करेगा, ताकि callers (platform, preloading और auth pre-flight tooling) उन्हें workflow definition से statically enumerate कर सकें। envelope को Execution Engine नियंत्रित करता है: resource types `roboflow_platform_model`, `roboflow_platform_project` और `third_party_model`प्रत्येक के साथ एक typed, serializable (pydantic) metadata entity होती है। Platform-model entries usage की प्रकृति भी बताते हैं: `required_action` (`access` — model entity को केवल platform पर reachable होना चाहिए, बनाम `execution` — model निष्पादित होता है) और, execution के लिए, `execution_location` (`local` / `remote` / `environment_defined` जब locality runtime पर `WORKFLOWS_STEP_EXECUTION_MODE`द्वारा तय की जाती है)। Blocks जो अपनी स्वयं की locality override से नियंत्रित हैं, उसे वहीं निर्दिष्ट करते हैं — SAM3 image blocks जब `SAM3_EXEC_MODE=remote` होता है तब कुछ भी घोषित नहीं करते (proxy execution configured model id को अनदेखा करता है और server-side पर एक fixed SAM3 चलाता है) और `environment_defined` अन्यथा। `None` लौटाना (default) का अर्थ है कि block अपनी dependencies घोषित नहीं करता — यह `[]`से अलग है, जो यह घोषित करता है कि किसी external resource की आवश्यकता नहीं है। Workflow selectors वाले field values (`$inputs.<name>` / `$steps.<name>.<property>`) verbatim रिपोर्ट किए जाते हैं; हर metadata entity `requires_runtime_resolution()` प्रकट करती है ताकि ऐसे references को concrete identifiers से अलग पहचाना जा सके। जिन declarations का अंतिम id field value से synthesized होता है (family prefixes जैसे `clip/<version>`catalog lookups), वे अतिरिक्त रूप से एक non-serializable `model_id_resolver` callable जोड़ते हैं जो substituted input value को executed id में बदलता है — serialization, JSON schema और equality से बाहर रखा जाता है। सभी core blocks जो models, Roboflow projects या third-party hosted models को reference करते हैं, इस method को implement करते हैं, और हर implementation उस model identifier को mirror करती है जिसे `run()` वास्तव में लोड करता है (version fields से synthesized ids सहित, जैसे `clip/<version>`). Project declarations उनके enabling controls का पालन करते हैं, जो static manifest values से तय होते हैं: Roboflow model blocks active-learning target को तब drop कर देते हैं जब `disable_active_learning` शाब्दिक रूप से `True` (default) होता है, और dataset-upload blocks तब कुछ भी घोषित नहीं करते जब `disable_sink` शाब्दिक रूप से `True`; selector-fed controls conservative may-need declaration बनाए रखते हैं। Introspection `active_learning_target_dataset` property पर रुक जाता है — active learning explicit target के बिना enabled होने पर कोई project model id से derive नहीं किया जाता। जो blocks अपने model weights को model manager के बाहर लोड करते हैं (SAM2/SAM3 video trackers, जो `AutoModel.from_pretrained`का उपयोग करते हैं), वे अभी जानबूझकर इस method को implement नहीं करते — उनकी dependencies घोषित नहीं रहतीं (`None`).
* **Dynamic (custom python) blocks अज्ञात dependencies रिपोर्ट करते हैं** — dynamic blocks के लिए synthesized manifests लौटाते हैं `None` से `discover_dependent_resources()`: python body static analysis के लिए opaque है, इसलिए "unknown" ही एकमात्र ईमानदार उत्तर है।
* **engine init पर declared Roboflow models का opt-in pre-loading** — `ExecutionEngine.init(...)` एक नया वैकल्पिक parameter स्वीकार करता है `dependencies_pre_init` (default `None`): pre-load करने के लिए dependent-resource type names की एक सूची, जिसमें `roboflow_platform_model` फिलहाल केवल समर्थित value है। सक्षम होने पर, engine सभी compiled steps की declared dependencies का अनुमान लगाता है (`deduce_blocks_dependencies` compiler utils में) और execution के लिए घोषित हर concrete Roboflow platform model को model manager में register करता है (दोनों लिए गए `init_parameters`से, जैसे API key भी) `init()` के दौरान — किसी भी run से पहले, ताकि first-inference latency अनुमानित रहे। जो declarations `$inputs.<name>` का संदर्भ देती हैं, उन्हें init पर load नहीं किया जा सकता; केवल **पहली** `run()` बार — runtime-input validation के बाद, ताकि invalid request न तो single attempt खपत करे और न downloads शुरू करे — engine उन्हें दिए गए runtime parameters (input defaults लागू करके) के विरुद्ध resolve करता है, attached होने पर declaration के `model_id_resolver` को लागू करता है (ताकि उदाहरण के लिए substituted CLIP version pre-load हो `clip/<version>`), बिल्कुल वही id जो execution उपयोग करता है), और उन models को register करता है जिनके identifiers concrete बन गए। resolver का लौटाना `None` यह घोषित करता है कि substituted value statically unresolvable है (जैसे Qwen का fine-tuned sentinel label, जिसका अंतिम id किसी अन्य input पर निर्भर करता है) — dependency छोड़ दी जाती है और execution time पर resolve होती है; submitted input value जिसे resolver संभाल नहीं सकता (जैसे unknown catalog label) `RuntimeInputError`उठाता है। Registration हर block के actual loader को mirror करती है: declarations non-serializable `model_registration_kwargs` धारण कर सकती हैं (जैसे `endpoint_type=CORE_MODEL` CLIP / OCR / SAM2 / YOLO-World-शैली के core models के लिए, जो `load_core_model()`से मेल खाते हैं)। प्रत्येक pre-loading pass के बाद engine सत्यापित करता है कि registered models अभी भी model manager में मौजूद हैं और जब size/memory-bounded manager ने उनमें से कुछ को evict कर दिया हो तो warning log करता है (वे execution time पर lazy तरीके से पुनः लोड होते हैं)। Pre-loading प्रभावी step execution mode का सम्मान करता है (explicit `step_execution_mode` init parameter, या `WORKFLOWS_STEP_EXECUTION_MODE` default): `environment_defined` declarations केवल तब pre-loaded होती हैं जब steps locally execute होते हैं, `local` declarations हमेशा होती हैं, और access-only declarations (कोई weights नहीं खींचे जाते), remote execution तथा `$steps.…`-fed identifiers कभी pre-loaded नहीं होते। `InferencePipeline.init_with_workflow(...)` इसे opt-in `workflows_dependencies_pre_init` parameter के रूप में उपलब्ध कराता है (default `None` — कोई pre-loading नहीं) — video processing को predictable startup से सबसे अधिक लाभ मिलता है।

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

**क्या बदला**

* **Offline mode remote Workflow step execution को अस्वीकार करता है** — जब `OFFLINE_MODE` enabled होता है, compiler `StepExecutionMode.REMOTE` को step initialization के दौरान अस्वीकार करता है (`WorkflowEnvironmentConfigurationError`) ताकि Workflows नेटवर्क access के बिना remote inference clients न खोल सकें। Local step execution warmed caches के विरुद्ध काम करना जारी रखता है।
* **उचित model access failure status codes** - स्थानीय workflow models लोड करते समय उठाई गई model-access विफलताएँ अब सामान्य HTTP 500 errors के रूप में दिखने के बजाय HTTP 402, 403, और 423 statuses को बनाए रखती हैं।

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

**क्या बदला**

**Future resolution** - कुछ steps अब `Future` objects emit कर सकते हैं जो output resolution को तब तक टालते हैं जब तक clients को outputs की आवश्यकता न हो। Downstream blocks के लिए इन futures को [step\_input\_assembler](https://github.com/roboflow/inference/blob/main/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py) में resolve किया जा रहा है, जबकि output निर्माण [output\_constructor](https://github.com/roboflow/inference/blob/main/inference/core/workflows/execution_engine/v1/executor/output_constructor.py) में coordinate conversion के साथ किया जाता है।

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

**क्या बदला**

* **dict step selectors के लिए case-वार execution branches** - जब कोई flow-control block एक `Dict[str, StepSelector]` property (List\[StepSelector] के बजाय) के अंदर step selectors घोषित करता है, तो compiler अब हर dictionary key के लिए अलग execution branch बनाता है। पहले एक ही property में हर selector एक branch साझा करता था, इसलिए block अपने targets तक स्वतंत्र रूप से route नहीं कर सकता था। Branch names अब dictionary key शामिल करते हैं (जैसे `List[StepSelector]`). List properties में रखे selectors (जैसे `Branch[$steps.switch -> cases[red]]`). साझा-branch व्यवहार पहले जैसा ही रखते हैं, इसलिए मौजूदा blocks अप्रभावित रहते हैं। यही परिवर्तन नए `next_steps`को सक्षम बनाता है `roboflow_core/switch_case@v1` block (`graph_constructor.establish_control_flow_edge`).
* **ठीक: दोहराए गए branch names वाले non-SIMD flow-control masks** - एक non-SIMD flow-control step जिसने एक ही list property के माध्यम से एक से अधिक target चुने, उसने `Attempted to re-register maks for execution branch`उठाया। Branch-mask registration अब register करने से पहले branch names को deduplicate करती है, जिससे crash ठीक हो गया (उदाहरण के लिए प्रभावित `ContinueIf` के साथ multiple `next_steps`; `execution_data_manager.manager._register_control_flow_output_for_non_simd_step`).

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

**क्या बदला**

* **नेस्टेड inner workflows में Dynamic blocks** - compiler अब root workflow और हर nested `dynamic_blocks_definitions` को हर `inner_workflow` child (depth-first) से एकत्र करता है, `manifest.block_type` के आधार पर deduplicate करता है (पहली occurrence जीतती है; duplicate छोड़ने पर warning log की जाती है), और merged list को `compile_dynamic_blocks` और inlining से पहले root definition पर hoist करता है। केवल nested workflow spec पर परिभाषित custom Python block types का उपयोग करने वाले child steps inlining के बाद सही ढंग से compile और run होते हैं।

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

**क्या बदला**

* ऐसे dictionaries को पहचानने की क्षमता जो values के रूप में static values और selectors के मिश्रण वाली हों — पिछले संस्करणों में केवल keys को selectors से map करने वाली dicts पहचानी जाती थीं, जिससे runtime में कुछ blocks refer किए गए values से सही ढंग से wire नहीं होते थे। परिवर्तन non-breaking है, लेकिन उन कुछ blocks को ठीक करता है जो पहले टूटे हुए थे।

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

{% hint style="info" %}
**नई सुविधा: compile-time inlining के माध्यम से nested workflows**

यह release **`roboflow_core/inner_workflow@v1`** block जोड़ता है ताकि workflow किसी अन्य workflow definition को embed कर सके (inline JSON या resolved from `workflow_workspace_id` / `workflow_id` / optional `workflow_version_id`)। Child inputs parent से **`parameter_bindings`** (child `inputs[].name` → parent selectors) के साथ जुड़े होते हैं। Compile time पर engine **inlines** nested steps को parent graph में; execution ordinary steps के समान path का उपयोग करती है (कोई अलग nested runtime नहीं)।
{% endhint %}

**क्या बदला**

* **Inner workflow block** - नया flow-control block type `roboflow_core/inner_workflow@v1` में पंजीकृत `roboflow_core`. Parent outputs child workflow JsonField outputs को इस रूप में refer कर सकते हैं `$steps.<inner_step_name>.<child_output_name>` जब तक inlining selectors को पुनर्लेखित नहीं कर देता।
* **Compile pipeline** - root definition parse करने से पहले, compiler: (1) **सामान्यीकृत करता है** references (default: Roboflow API + `workflows_core.api_key`, या custom `workflows_core.inner_workflow_spec_resolver`), (2) **composition को validate करता है** (acyclicity, max nesting depth, max inner-workflow count), (3) **inlines** सभी inner workflow steps को ordinary steps में बदल देता है, फिर parse, workflow specification validation, और execution graph construction के साथ जारी रखता है।
* **सीमाएँ (environment variables)** - `WORKFLOWS_MAX_INNER_WORKFLOW_DEPTH` (default `4`) root से containment depth को सीमित करता है; `WORKFLOWS_MAX_INNER_WORKFLOW_COUNT` (default `32`) nested definition में `inner_workflow` steps की कुल संख्या को सीमित करता है।
* **दस्तावेज़ीकरण** - देखें [Inner workflows (nested definitions)](/workflows/hi/developer-guide/developer-guide/inner-workflows.md) उपयोग, bindings, limits, और एक उदाहरण के लिए।

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

{% hint style="info" %}
**Additive change + bug fix के कारण एक breaking change, अपेक्षित प्रभाव न्यूनतम**

यह release Execution Engine को इस तरह विस्तारित करता है कि control flow द्वारा gated steps (जैसे एक `ContinueIf` block के बाद) तब भी चल सकें जब उनके पास **कोई data-derived lineage न हो** - यानी जब उन्हें upstream steps से batch-oriented inputs नहीं मिलते। Lineage और execution dimensionality अब control flow predecessor steps से derive की जा सकती हैं। मौजूदा workflows अप्रभावित हैं।

एक breaking change जोड़ा गया है वह उस bug fix के कारण है जो `Batch.remove_by_indices` को nested batches के साथ प्रभावित करता है (नीचे देखें); प्रभाव न्यूनतम रहने की उम्मीद है।
{% endhint %}

**क्या बदला**

* **Control flow lineage** - compiler अब control flow steps से आने वाली lineage को ट्रैक करता है (जैसे `ContinueIf`) के बाद की branches)। **control flow lineage support** की एक नई धारणा उपयोग की जाती है जब किसी step के पास batch-oriented data inputs नहीं होते लेकिन उससे पहले control flow steps होते हैं: step की execution slices और batch structure उन control flow predecessors से ली जाती है।
* **Compatibility check ढीला किया गया** - पहले, `verify_compatibility_of_input_data_lineage_with_control_flow_lineage` ने `ControlFlowDefinitionError` किसी भी ऐसे step के लिए उठाया जिसके control flow predecessors थे लेकिन data-derived lineage नहीं थी, इसलिए ऐसे steps compile नहीं हो सकते थे। वह check अब ढीला कर दिया गया है: जब किसी step के पास input data lineage नहीं होती, तब compatibility enforce नहीं की जाती और step की lineage control flow predecessor step lineage से derive की जाती है। कड़ा check तब भी चलता है जब step *के पास है* data-derived lineage, ताकि control flow और data lineage संगत बने रहें।
* **नए step patterns** - वे steps जो केवल control flow द्वारा triggered होते हैं और batch data consume नहीं करते, अब सही ढंग से चलते हैं। उदाहरण के लिए, आप `ContinueIf` के बाद email notifications भेज सकते हैं (या अन्य side-effect steps चला सकते हैं) `message_parameters`जैसे parameters में कोई data wire किए बिना; step नियंत्रण करने वाले step से ली गई lineage और dimensionality के साथ control flow branch प्रति एक बार execute होगा।
* **`Batch.remove_by_indices` nested batches के साथ (behavioral fix)** - via indices हटाते समय `Batch.remove_by_indices`, nested `Batch` elements अब उसी index set से recursively filtered होते हैं। परिणामस्वरूप, हटाए गए indices पर entries (सहित `None` values) अब nested batches से भी सही ढंग से हटा दी जाती हैं। पहले केवल top-level batch filtered होती थी; nested batches अपरिवर्तित रहती थीं।

  डिफ़ॉल्ट रूप से एक `WorkflowBlock`, `accepts_empty_values()`है `False`. जबकि इसे bypass किया गया था, ऐसे inputs consume करने वाले blocks पूरी तरह fail हो रहे थे, जैसे `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]
      ...
  ```

  यह परिवर्तन केवल जिस core block को प्रभावित करता है वह है `DimensionCollapseBlockV1` block, क्योंकि यह None values को फ़िल्टर किए बिना individual inputs को एक batch में wrap कर रहा था।

  ```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]}
  ```

  इस block का output downstream applications में उपयोग करते समय या तो पूरी तरह fail हो सकता था या None values को चुपचाप process कर सकता था, यदि वे उन values को स्वयं filter न करें।

  ऊपर को देखते हुए हमें लगता है कि प्रभाव न्यूनतम होगा।

## 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 blocks जो क्लाइंट की गलत कॉन्फ़िगरेशन (अमान्य Roboflow API key, अमान्य model ID, आदि) के कारण विफल होते हैं, अब `StepExecutionError` (और सर्वर से HTTP 500 प्रतिक्रिया) अब `ClientCausedStepExecutionError` (और संबंधित HTTP प्रतिक्रिया कोड, जैसे 400, 401, 403, 404)।
{% endhint %}

परिवर्तन से प्रभावित परिदृश्यों की सूची:

* Roboflow model का उपयोग करने वाला block अमान्य model ID परिभाषित करता है - अब `ClientCausedStepExecutionError` स्थिति कोड 400 के साथ
* Roboflow model का उपयोग करने वाला block अमान्य API key परिभाषित करता है - अब `ClientCausedStepExecutionError` स्थिति कोड 401 के साथ
* Roboflow model का उपयोग करने वाला block अमान्य API key परिभाषित करता है या संसाधन तक पहुँचने के लिए वैध key को scope के साथ गायब रखता है - अब `ClientCausedStepExecutionError` स्थिति कोड 403 के साथ
* Roboflow model का उपयोग करने वाला block ऐसा model परिभाषित करता है जो मौजूद नहीं है - अब `ClientCausedStepExecutionError` स्थिति कोड 404 के साथ

{% hint style="info" %}
**वापस लाना `legacy` त्रुटि प्रबंधन**

यदि आवश्यकता हो, तो त्रुटि हैंडलर के legacy व्यवहार को वापस लाना संभव है, जो संक्रमण अवधि में सहायक हो सकता है - बस पर्यावरणीय चर सेट करना होता है `DEFAULT_WORKFLOWS_STEP_ERROR_HANDLER=legacy`.
{% endhint %}

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

{% hint style="info" %}
**परिवर्तन पर ध्यान देने की आवश्यकता हो सकती है**

यह रिलीज़ बिना **मौजूदा workflows में किसी परिवर्तन की आवश्यकता के** अपग्रेड और नई सुविधाएँ प्रस्तुत करती है। कुछ blocks को Execution Engine की नवीनतम क्षमताओं का लाभ लेने के लिए अपग्रेड करने की आवश्यकता हो सकती है।
{% endhint %}

Execution Engine के पिछले संस्करणों में कुछ प्रकार के blocks के साथ इंटरैक्ट करते समय महत्वपूर्ण सीमाएँ थीं - विशेष रूप से वे जो Single Instruction, Multiple Data (SIMD) मोड में कार्य करते हैं। ये blocks एक साथ इनपुट के बैचों को प्रोसेस करने, प्रत्येक तत्व पर वही ऑपरेशन लागू करने, और पूरे बैच के लिए परिणाम लौटाने के लिए बनाए गए हैं।

उदाहरण के लिए, `run(...)` ऐसे block की method कुछ इस तरह दिख सकती है:

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

मैनिफेस्ट में, `image` फ़ील्ड को बैच स्वीकार करने वाला घोषित किया गया है।

समस्या तब उत्पन्न हुई जब इनपुट image ऐसे block से आती थी जो बैचों पर कार्य नहीं करता था। ऐसे मामलों में, Execution Engine व्यक्तिगत images से बैच बनाने में सक्षम नहीं था, जिसके परिणामस्वरूप अक्सर इस तरह की निराशाजनक compilation त्रुटियाँ आती थीं:

```
step `$steps.model` की property `images` में प्लग किया गया अमान्य संदर्भ पाया गया - step property 
सख्ती से batch-उन्मुख inputs की आवश्यकता रखती है, जबकि input selector में non-batch उन्मुख input मौजूद है - यह संकेत देता है 
कि आपके Workflow के निर्माण में समस्या है - आमतौर पर समस्या तब होती है जब non-batch उन्मुख step inputs 
non batch-उन्मुख steps या non-batch-उन्मुख inputs के outputs से भरे जाते हैं।
```

Execution Engine में `v1.6.0`, यह सीमा हटा दी गई है, जिससे निम्न व्यवहार प्रस्तुत होता है:

* जब यह पता चलता है कि किसी दिए गए input को batch-उन्मुख होना चाहिए, तो **Auto Batch Casting** नामक प्रक्रिया लागू की जाती है। यह input को स्वतः एक `Batch[T]`में बदल देती है। चूँकि सभी batch-mode inputs पहले से ही manifests में स्पष्ट रूप से दर्शाए गए थे, इसलिए अधिकांश blocks (नीचे बताए गए अपवादों को छोड़कर) बिना किसी आंतरिक परिवर्तन के इस अपग्रेड का लाभ उठाते हैं।
* auto-batch cast parameter की dimensionality (nesting का स्तर) compilation समय पर, workflow में विशिष्ट block के context के साथ-साथ उसके manifest के आधार पर निर्धारित की जाती है। यदि अन्य batch-उन्मुख inputs मौजूद हैं (जिन्हें *lineage supports*कहा जाता है), तो Execution Engine auto-casted batches बनाते समय उन्हें संदर्भ के रूप में उपयोग करता है। इससे यह सुनिश्चित होता है कि प्रत्येक batch dimension में तत्वों की संख्या step में फीड किए गए अन्य data से मेल खाती है (जैसे कि वास्तविक batch input प्रदान किए जाने पर अपेक्षित होता)। यदि कोई *lineage supports*नहीं हैं, या यदि block manifest इसकी आवश्यकता करता है (उदा. input dimensionality offset सेट है), तो अनुपस्थित dimensions को [`torch.unsqueeze(...)` operation](https://docs.pytorch.org/docs/stable/generated/torch.unsqueeze.html).
* इसके बाद step outputs का मूल्यांकन Auto Batch Casting context की उपस्थिति के विरुद्ध किया जाता है। मूल्यांकन के आधार पर, outputs या तो batches के रूप में या scalars के रूप में सहेजे जाते हैं, जिससे यह सुनिश्चित होता है कि casting का प्रभाव स्थानीय रहे, केवल उस अपवाद के साथ जहाँ output dimensionality परिवर्तन स्वयं block द्वारा लाया गया हो। इसके एक side effect के रूप में, अब यह संभव है कि:
  * **scalars से output batches बनाएँ** (जब step dimensionality बढ़ाता है), और
  * **batches को scalars में घटाएँ** (जब block dimensionality घटाता है)।
* दो संभावित friction points उत्पन्न होते हैं - पहला **जब कोई block batches स्वीकार नहीं करता** (और इसलिए batch-स्वीकार करने वाले inputs को घोषित नहीं करता) **output dimensionality घटाता है**. पिछले संस्करणों में, Execution Engine ने dimensionality wrapping लागू करके इसे संभाला: सभी batch-उन्मुख inputs को एक अतिरिक्त `Batch[T]` dimension के साथ wrap किया जाता था, जिससे block की `run(...)` method को list dimension के across reduce operations करने की अनुमति मिलती थी। लेकिन Auto Batch Casting के साथ, ऐसे blocks अब Execution Engine को इस बारे में स्पष्ट संकेत नहीं देते कि कुछ inputs scalars हैं या batches, जिससे casting nondeterministic हो जाती है। इसे संबोधित करने के लिए, एक नई manifest method प्रस्तुत की गई: `get_parameters_enforcing_auto_batch_casting(...)`. इस method को उन parameters की सूची लौटानी चाहिए जिनके लिए dimensionality कम होने पर batch casting लागू की जानी चाहिए। इसे किसी अन्य context में उपयोग करने की अपेक्षा नहीं है।

{% hint style="warning" %}
**मौजूदा blocks पर नई method का प्रभाव**

परिभाषित करने की आवश्यकता `get_parameters_enforcing_auto_batch_casting(...)` ऊपर वर्णित मामले में Auto Batch Casting सुविधा का पूर्ण उपयोग करने के लिए method की आवश्यकता कठोर नहीं है। यदि block को नहीं बदला जाता है, तो एकमात्र प्रभाव यह होगा कि workflows जो **पहले विफल हो रहे थे** compilation error के साथ काम कर सकते हैं या **runtime error**के साथ विफल हो सकते हैं, यह block की `run(...)` method implementation के विवरण पर निर्भर करता है।
{% endhint %}

* दूसरा friction point तब उत्पन्न होता है जब कोई block `get_parameters_accepting_batches_and_scalars(...)` का उपयोग करके batches और scalars दोनों का समर्थन करने वाले input fields घोषित करता है - डिफ़ॉल्ट रूप से, Execution Engine ऐसे parameters के लिए auto-casting को छोड़ देगा, क्योंकि method ऐतिहासिक रूप से **scalars को batches में broadcast करने की block की स्वयं की क्षमता घोषित करने का हमेशा एक तरीका रहा है** - देखें [का implementation `roboflow_core/detections_transformation@v1`](https://github.com/roboflow/inference/blob/main/inference/core/workflows/core_steps/transformations/detections_transformation/v1.py) block. एक तरह से, Auto Batch Casting *redundant* है ऐसे blocks के लिए - इसलिए हमारा सुझाव है कि उन्हें जैसा है वैसा ही छोड़ दिया जाए और `get_parameters_enforcing_auto_batch_casting(...)` के बजाय उपयोग करने के लिए upgrade किया जाए `get_parameters_accepting_batches_and_scalars(...)` ऐसे blocks के नए संस्करणों में।
* पिछले संस्करणों में, एक कठोर constraint था: dimensionality collapse केवल levels ≥ 2 पर ही हो सकता था (अर्थात केवल nested batches पर)। यह सीमा अब हटा दी गई है। Dimensionality collapse blocks scalars पर भी कार्य कर सकते हैं, जहाँ output dimensionality शून्य आधार से “टकराकर” वापस उछलती है।

एक **मुख्य परिवर्तन outputs के निर्माण के तरीके में है।** Execution Error के पहले के संस्करणों में, किसी block को सीधे first dimension level पर एक `Batch[X]` उत्पन्न करने की अनुमति नहीं थी - वह स्थान input batches पर mapping के लिए आरक्षित था। संस्करण `v1.6.0`से शुरू होकर, यह प्रतिबंध हटा दिया गया है।

पहले, outputs हमेशा elements की एक list के रूप में लौटाए जाते थे:

* जो input batches के साथ aligned होती थी, या
* यदि केवल scalars input के रूप में दिए गए थे, तो एक single-element list।

इससे एक प्रश्न उठा: यदि कोई block अब first dimension level पर batch उत्पन्न करता है, तो क्या होना चाहिए? हम इसे input-based outputs के साथ आसानी से `zip(...)` नहीं कर सकते, क्योंकि newly generated batches का आकार input elements की संख्या से मेल नहीं भी खा सकता है - जिससे operation अस्पष्ट हो जाता है।

इसे हल करने के लिए, हमने निम्न नियम अपनाया:

* स्थिति को ऐसे मानें जैसे कि एक **"dummy" input batch of size 1**.
* मौजूद हो
* scalars inputs से उत्पन्न सभी batches को उनकी वास्तविकता से एक स्तर अधिक गहरा मानें।
* Input batch निष्पादन के परिणामस्वरूप गायब हो सकता है, लेकिन जब ऐसा होता है और नया first-level dimension उभरता है, तब भी outputs की संगति सुनिश्चित करने के लिए उसे आभासी रूप से nested माना जाएगा।

**उदाहरण:**

```
(कोई INPUTS नहीं)    IMAGE FETCHER BLOCK --> image --> OD MODEL --> predictons --> CROPS --> output होगा: ["crops": [<crop>, <crop>, ...]] 
```

यह ध्यान देना महत्वपूर्ण है कि **पहले बनाए गए मान्य workflows से उत्पन्न परिणाम वही होंगे** और यह परिवर्तन केवल नई कार्यक्षमताओं का उपयोग करने के लिए बनाए गए नए workflows को प्रभावित करेगा।

### माइग्रेशन गाइड

<details>

<summary>`get_parameters_enforcing_auto_batch_casting(...)` method जोड़ना</summary>

जो blocks output dimensionality घटाते हैं और batch-उन्मुख inputs परिभाषित नहीं करते, उन्हें उन सभी inputs को घोषित करना होगा जिन्हें implementation के अनुसार `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:
        यह वह parameter है जिसे auto-batch cast नहीं किया जाएगा, यह मेरा 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` उन fields की घोषणा जोड़नी होगी जो enforced auto-batch casting के अधीन होंगे
* ऊपर के परिणामस्वरूप, run method के input parameters (पंक्तियाँ `53-54`) को `Batch[T]` द्वारा wrap किया जाएगा।

</details>

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

{% hint style="info" %}
**परिवर्तन के लिए कोई कार्रवाई आवश्यक नहीं है**

यह परिवर्तन Workflows उपयोगकर्ताओं से किसी बदलाव की आवश्यकता नहीं रखता। यह केवल performance optimisation है।
{% endhint %}

* की init method में नया parameter प्रस्तुत किया गया `BaseExecutionEngine` class - `executor` जो Python के instance को स्वीकार कर सकता है `ThreadPoolExecutor` जिसका उपयोग execution engine द्वारा किया जाएगा। इस परिवर्तन के कारण, processing तेज़ होनी चाहिए, क्योंकि प्रत्येक `BaseExecutionEngine.run(...)` को समर्पित instance की आवश्यकता नहीं होगी `ThreadPoolExecutor` जैसा कि अब तक था। इसके अलावा, हम threads spawning को काफ़ी सीमित कर रहे हैं, जो कुछ installations में लाभदायक भी हो सकता है।
* परिवर्तन के बावजूद, Execution Engine concurrently executed steps की सीमा बनाए रखता है - एक समय में executor के माध्यम से चलने वाले steps की संख्या सीमित करके (क्योंकि Execution Engine अब `ThreadPoolExecutor` creation के नियंत्रण में नहीं है, और pool में अधिक workers उपलब्ध हो सकते हैं)।

<details>

<summary>Execution Engine में `ThreadPoolExecutor` कैसे inject करें?</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/hi/developer-guide/developer-guide/kinds/secret.md) प्रमाण-पत्रों को दर्शाने के लिए। **मौजूदा blocks के लिए किसी कार्रवाई की आवश्यकता नहीं** है, फिर भी अपेक्षा है कि समय के साथ block developers को इस kind का उपयोग करना चाहिए, जब भी block को parameter के रूप में secret value स्वीकार करनी हो।
* में प्रस्तुत हुई results serialization की समस्या ठीक की गई `v1.3.0` - गलती से, Execution Engine non-batch उन्मुख outputs को serialize नहीं कर रहा था।
* steps के लिए inputs तैयार करने में Execution Engine की bug ठीक की गई। पहले non-SIMD steps के लिए, runtime में inputs इकट्ठा करते समय, `WorkflowBlockManifest.accepts_empty_input()` method परिणाम को अनदेखा किया जा रहा था - जिससे वह bug उत्पन्न होता था जब एक non-SIMD step downstream blocks को खाली values फीड कर रहा था। इसके अलावा, `v1.3.0`में किए गए परिवर्तनों के आलोक में, जिनके कारण non-SIMD blocks आसानी से downstream SIMD steps के लिए inputs फीड कर सकते हैं - यह जाँचना आवश्यक है कि upstream non-SIMD block ने non-empty परिणाम दिए हैं या नहीं (क्योंकि SIMD block खाली परिणाम स्वीकार नहीं कर सकता)। यह जाँच जोड़ दी गई है। **मौजूदा blocks के लिए किसी कार्रवाई की आवश्यकता नहीं** मौजूदा blocks के लिए, लेकिन यह fix पहले से टूटे हुए Workflows को ठीक कर सकता है।

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

* ऐसा परिवर्तन प्रस्तुत किया गया जिसने प्रत्येक kind को serializer और deserializer परिभाषित करने की अनुमति दी। यह परिवर्तन Workflows plugins को Execution Engine से अलग करता है और ecosystem को external systems के साथ एकीकृत करना संभव बनाता है जिन्हें wire के माध्यम से data transfer की आवश्यकता होती है। [Blocks bundling](/workflows/hi/developer-guide/developer-guide/block-bundling.md) पृष्ठ को इस परिवर्तन को दर्शाने के लिए अद्यतन किया गया।
* *Kinds* में परिभाषित `roboflow_core` plugin को उपयुक्त serializers और deserializers दिए गए थे
* Workflows Compiler और Execution Engine को **किसी भी&#x20;*****kind***&#x915;े batch-उन्मुख inputs का समर्थन करने के लिए उन्नत किया गया, जबकि उससे पहले के संस्करण `v1.3.0`केवल `image` और `video_metadata` kinds को batch-उन्मुख inputs के रूप में ले सकते थे (यह Execution Engine के स्तर पर प्रस्तुत की गई kind को internal data format से दुर्भाग्यपूर्ण और अनावश्यक coupling का परिणाम था **Execution Engine के स्तर पर**)। परिवर्तन के परिणामस्वरूप:
  * **नया input type प्रस्तुत किया गया:** `WorkflowBatchInput` अब से batch-उन्मुख inputs को दर्शाने के लिए इसका उपयोग किया जाना चाहिए (और उन्हें स्पष्ट रूप से `WorkflowParameters`). `WorkflowBatchInput` से अलग करना चाहिए ताकि उपयोगकर्ता दोनों को परिभाषित कर सकें [*kind*](/workflows/hi/developer-guide/developer-guide/kinds.md) data का और उसके [*dimensionality*](/workflows/hi/developer-guide/developer-guide/workflow-execution.md#steps-interactions-with-data). नया input type प्रभावी रूप से सभी पिछले batch-उन्मुख inputs का superset है: `WorkflowImage` और `WorkflowVideoMetadata`, जिन्हें **समर्थित रखा जाएगा**, लेकिन **Execution Engine में हटाए जाएंगे `v2`**. हम नए input format के अनुसार ढलने की सलाह देते हैं, फिर भी अभी यह आवश्यकता कठोर नहीं है - क्योंकि Execution Engine को अब input data की स्पष्ट परिभाषा चाहिए *kind* ताकि data deserializer को सही ढंग से चुना जा सके। भविष्य में ऐसा नहीं भी हो सकता, क्योंकि अधिकांश मामलों में batch-उन्मुख data *kind* compiler द्वारा अनुमानित किया जा सकता है (फिर भी यह सुविधा अभी लागू नहीं की गई है)।
  * **नई selector type annotation प्रस्तुत की गई** - जिसका नाम सरल रूप से `Selector(...)`. `Selector(...)` को प्रतिस्थापित करना है `StepOutputSelector`, `WorkflowImageSelector`, `StepOutputImageSelector`, `WorkflowVideoMetadataSelector` और `WorkflowParameterSelector` block manifests में, जिससे developers यह व्यक्त कर सकें कि विशिष्ट step manifest property विशिष्ट *kind*का selector या दोनों में से कोई भी रख सकती है। उल्लिखित पुरानी annotation types **को अप्रचलित माना जाना चाहिए**, हम `Selector(...)`.
  * में माइग्रेट करने की सलाह देते हैं। selectors type annotations के सरलीकरण के परिणामस्वरूप, पुराना selector अब blocks के' `run(...)` method किस parameter [`Batch[X]` container](/workflows/hi/developer-guide/developer-guide/data-representations.md#batch)के रूप में Execution Engine द्वारा wrapped होकर भेजी जाएगी। पुरानी selectors type annotations और `block_manifest.accepts_batch_input()` method के बजाय, हम दो methods में स्विच करने का प्रस्ताव रखते हैं जो स्पष्ट रूप से उन parameters को परिभाषित करती हैं जिन्हें batch-उन्मुख data से feed किए जाने की अपेक्षा है (`block_manifest.get_parameters_accepting_batches()`) और वे parameters जो दोनों को स्वीकार कर सकते हैं *batches* और *scalar* values (`block_manifest.get_parameters_accepting_batches_and_scalars()`)। `block_manifest.accepts_batch_input()` का return value दो नई methods के परिणामों पर आधारित है। यह परिवर्तन **non-breaking**है, क्योंकि कोई भी मौजूदा block जो batches प्रोसेस करने में सक्षम था, उसके लिए `block_manifest.accepts_batch_input()` method returning `True` और batch-उन्मुख data को इंगित करने वाली उपयुक्त selector type annotation का उपयोग करना आवश्यक रहा होगा।
* परिवर्तनों के परिणामस्वरूप, अब यह संभव है कि **किसी भी मनचाही workflows को steps के उपसमूह निष्पादित करने वाले कई workflows में विभाजित करें**, जिससे debuggers जैसे उपकरण बनाना संभव होता है।

**ब्रेकिंग परिवर्तन नियोजित - Execution Engine `v2.0.0`**

* `WorkflowImage` और `WorkflowVideoMetadata` inputs Workflows ecosystem से हटा दिए जाएंगे।
* `StepOutputSelector,` WorkflowImageSelector`,` StepOutputImageSelector`,` WorkflowVideoMetadataSelector`और`WorkflowParameterSelector\` type annotations जो block manifests में उपयोग की जाती हैं, Workflows ecosystem से हटा दी जाएँगी। {% hint %}

### माइग्रेशन गाइड

<details>

<summary>Kinds के serializers और deserializers</summary>

अपना Workflows plugin बनाते समय आप Workflows kinds के लिए custom serializers और deserializers प्रस्तुत कर सकते हैं *kinds*. ऐसा करने के लिए, बस निम्न dictionaries को plugin के main module में रखें (उसी स्थान पर जहाँ आप `load_blocks(...)` function):

```python
from typing import Any

def serialize_kind(value: Any) -> Any:
  # यहाँ वह code रखें जिसका उपयोग
  # internal Workflows data representation को 
  # external representation में बदलने के लिए किया जाएगा (जिसे JSON में wire के माध्यम से भेजा जा सकता है,
  # Python के default JSON encoder का उपयोग करके)।
  pass

def deserialize_kind(parameter_name: str, value: Any) -> Any:
  # यहाँ वह code रखें जिसका उपयोग 
  # wire के माध्यम से Execution Engine में भेजे गए data को decode करने के लिए किया जाएगा
  # और उसे उचित internal Workflows data representation में बदलने के लिए किया जाएगा
  # जिसे blocks समझते हैं।
  pass

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

</details>

<details>

<summary>सेलेक्टर्स के लिए नया type annotation - `Batch[X]` इनपुट के बिना blocks</summary>

Blocks manifest हो सकता है **वैकल्पिक रूप से** उपयोग करने के लिए अपडेट किया जा सकता है `सेलेक्टर` निम्न प्रकार से:

```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>सेलेक्टर्स के लिए नया type annotation - `Batch[X]` इनपुट वाले blocks</summary>

Blocks manifest हो सकता है **वैकल्पिक रूप से** उपयोग करने के लिए अपडेट किया जा सकता है `सेलेक्टर` निम्न प्रकार से:

```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"]
```

कृपया यह बताएं कि:

* यह `डेटा` मूल उदाहरण में property दोनों को स्वीकार कर सकती थी **batches** डेटा और **scalar** मानों को बैच-उन्मुख डेटा के selector (`StepOutputSelector`) और *scalar* डेटा (`WorkflowParameterSelector`). अब यही द्वारा प्रदर्शित होता है `Selector(...)` type annotation और return value से `get_parameters_accepting_batches_and_scalars(...)` method.

</details>

<details>

<summary>वर्कफ़्लो परिभाषाओं में नए inputs</summary>

जिस किसी ने भी इनमें से किसी का उपयोग किया है `WorkflowImage` या `WorkflowVideoMetadata` अपने Workflows definition में inputs **वैकल्पिक रूप से** में migrate कर सकते हैं `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` फ़ील्ड खाली रखने से कुछ डेटा - जैसे images - को सही ढंग से डीसीरियलाइज़ होने से रोका जा सकता है।**

**नोट**

यदि आपको यह तरीका पसंद नहीं है कि डेटा serialized होता है in `roboflow_core` प्लगइन, तो serialization methods को बदलने के लिए स्वतंत्र महसूस करें *kinds*, बस अपने प्लगइन में function को register करके और उसे Execution Engine में load करके - जो serializer/deserializer अंतिम रूप से परिभाषित होगा, वही उपयोग में रहेगा।

</details>

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

* यह [`video_metadata` kind](/workflows/hi/developer-guide/developer-guide/kinds/video-metadata.md) को deprecated कर दिया गया है, और हम **भविष्य में blocks बनाने के लिए इसके उपयोग को बंद करने की दृढ़ता से सिफारिश करते हैं**। विकल्प के रूप में, [`image` kind](/workflows/hi/developer-guide/developer-guide/kinds/image.md) को वही metadata सपोर्ट करने के लिए विस्तारित किया गया है जैसा कि [`video_metadata` kind](/workflows/hi/developer-guide/developer-guide/kinds/video-metadata.md), जिसे अब वैकल्पिक रूप से प्रदान किया जा सकता है। यह अपडेट **non-breaking** मौजूदा blocks के लिए है, लेकिन **कुछ पुराने blocks** जो images उत्पन्न करते हैं **असंगत हो सकते हैं** साथ **भविष्य के** video processing blocks.

<details>

<summary>संभावित blocks असंगतता</summary>

जैसा कि पहले बताया गया है, जोड़ना `video_metadata` को internal representation में एक वैकल्पिक field के रूप में [`image` kind](/workflows/hi/developer-guide/developer-guide/kinds/image.md) (`WorkflowImageData` class) मौजूदा blocks के बीच कुछ friction पैदा कर सकता है जो आउटपुट करते हैं [`image` kind](/workflows/hi/developer-guide/developer-guide/kinds/image.md) और भविष्य के video processing blocks जो इस पर निर्भर करते हैं `video_metadata` का हिस्सा होने पर `image` representation.

समस्या इसलिए आती है क्योंकि, जबकि हम प्रदान कर सकते हैं **डिफ़ॉल्ट** के लिए मान `video_metadata` में `image` उन्हें इनपुट से स्पष्ट रूप से कॉपी किए बिना, ऊपर की ओर जोड़ा गया कोई भी गैर-डिफ़ॉल्ट metadata खो सकता है। इससे ऐसे downstream blocks हो सकते हैं जो इस पर निर्भर करते हैं `video_metadata` अपेक्षा के अनुरूप काम न करें।

हमने सभी मौजूदा `roboflow_core` blocks को इसे ध्यान में रखते हुए अपडेट किया है, लेकिन external repositories में इस परिवर्तन से पहले बनाए गए blocks उन workflows में समस्याएँ पैदा कर सकते हैं जहाँ उनके output images का उपयोग video processing blocks द्वारा किया जाता है।

</details>

* यद्यपि deprecated [`video_metadata` kind](/workflows/hi/developer-guide/developer-guide/kinds/video-metadata.md) अभी भी उपयोग के लिए उपलब्ध है, इसे Execution Engine version में पूरी तरह से हटा दिया जाएगा `v2.0.0`.

{% hint style="warning" %}
**ब्रेकिंग परिवर्तन नियोजित - Execution Engine `v2.0.0`**

[`video_metadata` kind](/workflows/hi/developer-guide/developer-guide/kinds/video-metadata.md) को deprecated कर दिया गया है और हटाया जाएगा `v2.0.0`
{% endhint %}

* ऊपर बताए गए परिवर्तनों के परिणामस्वरूप, की internal representation [`image` kind](/workflows/hi/developer-guide/developer-guide/kinds/image.md) को एक नए `video_metadata` property को शामिल करने के लिए अपडेट किया गया है। इस property को constructor में वैकल्पिक रूप से सेट किया जा सकता है; यदि इसे प्रदान नहीं किया जाता, तो उचित डिफ़ॉल्ट्स वाला एक default value उपयोग किया जाएगा। blocks के भीतर metadata manipulation को सरल बनाने के लिए, हमने दो नए class methods पेश किए हैं: `WorkflowImageData.copy_and_replace(...)` और `WorkflowImageData.create_crop(...)`। अधिक विवरण के लिए, अपडेट किए गए [`WoorkflowImageData` उपयोग मार्गदर्शिका](/workflows/hi/developer-guide/developer-guide/data-representations.md#workflowimagedata).
